Java实现接口RSA2校验

6 篇文章 0 订阅
3 篇文章 0 订阅

接口RSA2验签

由于没有找到网上比较全的资料,所以自己就找资料总结了一下,可以供大家参考,当然,这个写的比较简单,这个可以自己根据业务去修改,希望最大家有帮助

一、自定义注解

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Encryption {
}

二、AOP

@Slf4j
@Aspect
@Component
public class EncryptionAspect {


    @Pointcut("@annotation(com.fly.springbootmybatis.annotation.Encryption)")
    public void encryption() {
    }

    @Before("encryption()")
    public void LogPrintln(JoinPoint point) throws JsonProcessingException {
        Object[] args = point.getArgs();
        ApiBaseRequest arg = (ApiBaseRequest) args[0];
        String sign = arg.getSign();
        String body = arg.getBiz_content();
        if (StringUtils.isNotBlank(sign) && StringUtils.isNotBlank(body)) {
            boolean isSign = RSA2Utils.verify256(body.getBytes(StandardCharsets.UTF_8),sign, SystemUtils.API_RSA2_SIGN_PUBLIC_KEY);
            if (!isSign) {
                throw new ApiException(ResultEnum.SIGN_ERROR);
            }
        } else {
            throw new ApiException(ResultEnum.SIGN_ERROR);
        }
    }
}

三、通用参数实体类

@Data
public class ApiBaseRequest implements Serializable {

    private static final long serialVersionUID = 1L;

    @NotBlank(message = "请求ID不能为空")
    private String appId;
    
    private String format;

    private String charset;

    private String version = "1.0";

    @NotBlank(message = "签名不能为空")
    private String sign;

    @NotBlank(message = "时间戳不能为空")
    private String timestamp;

    @NotBlank(message = "请求参数不能为空")
    private String biz_content;
}

四、全局异常拦截

/**
 * 全局处理异常类
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {


    /**
     * 处理业务异常
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = BusinessException.class)
    public AjaxResult businessExceptionHandler(BusinessException e) {
        log.error(e.getMessage());
        return AjaxResult.error(e.getCode(),e.getMessage());
    }

    /**
     * 处理接口异常
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = ApiException.class)
    public AjaxResult ApiExceptionHandler(ApiException e) {
        log.error(e.getMessage());
        return AjaxResult.error(e.getCode(),e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(value = FileException.class)
    public AjaxResult fileExceptionHandler(FileException e) {
        log.error(e.getMessage());
        return AjaxResult.error(e.getCode(),e.getMessage());
    }

    /**
     * 请求方式不支持
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public AjaxResult handleException(HttpRequestMethodNotSupportedException e) {
        log.error(e.getMessage());
        return AjaxResult.error(ResultEnum.NOT_REQUEST_METHOD);
    }


    /**
     * 处理JSR303验证异常
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class, ValidateException.class})
    public AjaxResult handleVaildException(Exception e) {
        BindingResult bindingResult = null;
        if (e instanceof MethodArgumentNotValidException) {
            bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
        } else if (e instanceof BindException) {
            bindingResult = ((BindException) e).getBindingResult();
        } else if (e instanceof ValidateException) {
            return AjaxResult.error(((ValidateException) e).getCode(),e.getMessage(),((ValidateException) e).getData());
        }
        Map<String, String> errorMap = new HashMap<>(16);
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        fieldErrors.forEach(error -> errorMap.put(error.getField(), error.getDefaultMessage()));
        log.info("------参数校验失败:{}", errorMap);
        return AjaxResult.error(ResultEnum.ILLEGAL_PARAMETER.getCode(),ResultEnum.ILLEGAL_PARAMETER.getMsg(),errorMap);
    }

    /**
     * 处理上传文件过大异常
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = MaxUploadSizeExceededException.class)
    public AjaxResult fileSizeExceededException(MaxUploadSizeExceededException e){
        log.error(e.getMessage());
        return AjaxResult.error(ResultEnum.FILE_MAX_LIMIT);
    }

    /**
     * 处理其他异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public ModelAndView exceptionHandler(Exception e) {
        log.error(e.getMessage());
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("5xx");
        return modelAndView;
    }
}

五、RSA2加密工具类

@Slf4j
public class RSA2Utils {
    // 算法类别
    private final static String SIGN_TYPE = "RSA";
    // 算法位数
    private final static Integer KEY_SIZE = 2048;

    private RSA2Utils(){};

    /**
     * 生成公私钥
     */
    public static Map<String, String> getPublicPrivateKey() {
        Map<String, String> pubPriKey = new HashMap<>();
        KeyPair keyPair = KeyUtil.generateKeyPair(SIGN_TYPE, KEY_SIZE);
        String publicKeyStr = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        String privateKeyStr = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
        pubPriKey.put("publicKey", publicKeyStr);
        pubPriKey.put("privateKey", privateKeyStr);
        return pubPriKey;
    }

    /**
     * 实例化公钥
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE);
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 实例化私钥
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 签名
     */
    public static String sign256(byte[] signData, String priKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(priKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE);
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            Signature si = Signature.getInstance(SignAlgorithm.SHA256withRSA.getValue());
            si.initSign(privateKey);
            si.update(signData);
            byte[] sign = si.sign();
            return Base64.getEncoder().encodeToString(sign);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 验签
     */
    public static boolean verify256(byte[] dataBytes, String sign, String pubkey) {
        boolean flag = false;
        try {
            byte[] signByte = Base64.getDecoder().decode(sign);
            byte[] encodedKey = Base64.getDecoder().decode(pubkey);
            Signature verf = Signature.getInstance(SignAlgorithm.SHA256withRSA.getValue());
            KeyFactory keyFac = KeyFactory.getInstance(SIGN_TYPE);
            PublicKey puk = keyFac.generatePublic(new X509EncodedKeySpec(encodedKey));
            verf.initVerify(puk);
            verf.update(dataBytes);
            flag = verf.verify(signByte);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return flag;
    }


    /**
     * RSA2公钥加密
     */
    public static byte[] encyptByPublickey(byte[] data, String pubkey) throws Exception {
        Cipher cipher = Cipher.getInstance(SIGN_TYPE);
        cipher.init(Cipher.ENCRYPT_MODE,getPublicKey(pubkey));
        return cipher.doFinal(data);
    }

    /**
     * RSA2私钥解密
     */
    public static byte[] decryptByPrivateKey(byte[] content, String privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(SIGN_TYPE);
        cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
        return cipher.doFinal(content);
    }
}

六、其他类

@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum ResultEnum {
    // 数据操作错误定义
    NO_PERMISSION(403, "权限不足"),
    NO_AUTH(401, "未登录"),
    NOT_FOUND(404, "未找到该资源"),
    NOT_REQUEST_METHOD(405,"该请求方式不支持"),
    INTERNAL_SERVER_ERROR(500, "服务器异常请联系管理员"),

    SUCCESS(20000, "成功"),
    FAIL(10000,"失败"),
    FILE_MAX_LIMIT(10001,"单个文件上传不超过10MB,多个文件上传不超过100MB"),
    ILLEGAL_PARAMETER(10002,"非法参数"),
    CONVERSION_ERROR(10003,"参数转换错误"),

    FILE_READ_ERROR(10004,"文件读取失败"),

    SIGN_ERROR(10006,"验签失败"),

    REQUEST_ERROR(10007,"请求失效"),

    FREQUENT_REQUEST(10008,"请求过于频繁,请稍后再试");

    /**
     * 错误码
     */
    private Integer code;

    /**
     * 错误信息
     */
    private String msg;

}

public class ApiException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    /**
     * 状态码
     */
    private Integer code;


    /**
     * 错误提示
     */
    private String message;


    public ApiException() {

    }

    public ApiException(String message) {
        this.message = message;
    }

    public ApiException(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public ApiException(ResultEnum resultEnum) {
        this.code = resultEnum.getCode();
        this.message = resultEnum.getMsg();
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }


    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1、数字签名原理 用RSA算法做数字签名,总的来说,就是签名者用私钥参数d加密,也就是签名;验证者用签字者的公钥参数e解密来完成认证。 下面简要描述数字签名和认证的过程。 (1)、生成密钥 为用户随机生成一对密钥:公钥(e,n)和私钥(d,n). (2)、签名过程 a) 计算消息的散列值H(M). b) 用私钥(d,n)加密散列值:s=(H(M)) mod n,签名结果就是s. c) 发送消息和签名(M,s). (3)、认证过程 a) 取得发送方的公钥(e,n). b) 解密签名s:h=s mod n. c) 计算消息的散列值H(M). d) 比较,如果h=H(M),表示签名有效;否则,签名无效。 根据上面的过程,我们可以得到RSA数字签名的框图如图2-1: 图 2-1 RSA数字签名框图 2、 假设Alice想和Bob通信,以本地两个文件夹Alice和Bob模拟两个用户,实现消息M和签名的模拟分发 (1)、Alice通过RSA算法生成一对密钥:公钥(e,n)和私钥(d,n),将公私钥分别存入pubKey.txt和priKey.txt中。 pubKey.txt中公钥如下: priKey.txt中私钥如下: (2)、将Alice中的pubKey.txt拷到Bob中,模拟公玥的分发。 (3)、将Alice中的消息info.txt做散列,将散列后的值存入hashInfo.txt中。 (4)、将Alice中的消息hashInfo.txt和签名sign.txt拷到Bob中,实现M密文状态下的签名与模拟分发、消息传递。 (5)Bob取得公钥pubKey.txt,用公钥解密签名,计算消息的散列值H(M).比较,如果h=H(M),表示签名有效;否则,签名无效。 后台运行结果如下:
Java RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,它使用了一对公钥和私钥进行加密和解密。接口安全是指在网络通信中保护接口的安全性,防止未经授权的访问和数据泄露。下面是使用Java RSA实现接口安全的方法: 1. 生成密钥对:首先,需要使用Java的密钥工具类生成一对RSA密钥对,这对密钥包括公钥和私钥。公钥用于加密数据,私钥用于解密数据。 2. 加密数据:在发送数据之前,可以使用接收方的公钥对数据进行加密。发送方使用Java RSA的加密算法,将数据加密后发送给接收方。 3. 解密数据:接收方收到加密数据后,使用自己的私钥进行解密。通过Java RSA的解密算法,接收方可以还原出原始数据。 4. 签名验证:为了确保接口的真实性和完整性,可以使用RSA的数字签名机制。发送方使用自己的私钥对数据进行签名,接收方使用发送方的公钥对签名进行验证。这样可以确保数据的来源可信,并且未被篡改。 5. 密钥保护:公钥和私钥都是非常敏感的信息,需要进行保护。可以使用Java的密钥库将密钥保存在安全的位置,并设置访问权限,确保只有授权的人可以使用。 通过使用Java RSA算法,可以实现接口的安全性。加密和解密数据可以防止数据被窃取,在数据传输过程中防止被篡改,数字签名可以保证数据的可靠性。同时,合理保护密钥也是保证接口安全的重要措施之一。总之,Java RSA可以作为一种有效的手段来实现接口安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fly狮子座

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值