当前位置:   article > 正文

JAVA 使用RSA算法进行数字签名验证-附完整代码_java rsa验签

java rsa验签

前言:

        公司项目是有做资金管理相关的,涉及到充值,提现,转账等关键性的功能,需要保证数据传输的安全性,所以使用了较为简单的RSA进行生成秘钥且每个接口都需要做验签。

简介:

RSA是一种非对称加密算法,它是由Rivest-Shamir-Adleman三位密码学家于1978年提出的。

RSA算法的加密规则如下:

  1. 钥匙生成:RSA算法使用两个密钥,一个是公钥(public key),用于加密数据,另一个是私钥(private key),用于解密数据。首先,密钥生成者生成一对公钥和私钥,其中公钥可以公开给任何人使用,而私钥必须保密。

  2. 加密过程:发送方使用接收方的公钥对数据进行加密。发送方将数据按照一定的规则进行转换,并使用公钥进行加密操作。加密后的数据将无法直接被解密,只能使用私钥才能将其解密。

  3. 解密过程:接收方使用自己的私钥对加密后的数据进行解密。接收方使用私钥对加密后的数据进行解密操作,从而得到原始的明文数据。

RSA算法的安全性基于两个数学难题:

  1. 质因数分解问题:将一个大的合数(通常是两个大素数的乘积)分解成质数的乘积。这个问题在目前的计算能力下非常困难。

  2. 数论中的指数问题:计算一个大数的指数函数的反函数。这个问题同样在目前的计算能力下非常困难。

通过利用这两个数学难题,RSA算法能够保证数据的加密和解密过程的安全性,确保只有持有私钥的人才能够解密数据。

本次案例用于签名验证,使用私钥用于数字签名,公钥用于验证签名的有效性

测试代码:

  1. public static void main(String[] args) {
  2. Entity entity = new Entity();
  3. // 使用RSA算法生成 公钥与私钥, 生成的公私钥 是一一对应的。
  4. createRSAKey(entity);
  5. String body = "123456";
  6. String body2 = "77897";
  7. // 将入参数据以及私钥进行数字加签
  8. String sign = sign(body, entity.getPrivateKey());
  9. // 根据入参数据以及公钥进行验证签名,若入参数据body被修改或者秘钥不正确都会导致验签失败;例如加签使用body,验签使用body2则导致验签失败
  10. boolean verifyFlag = verify(body,entity.getPublicKey(), sign);
  11. if (verifyFlag) {
  12. logger.info("验签成功");
  13. } else {
  14. logger.info("验签失败");
  15. }
  16. }

1. 根据RSA生成一对秘钥

构建保存秘钥的实体类Entity

  1. @Data
  2. @Builder
  3. @AllArgsConstructor
  4. @NoArgsConstructor
  5. public class Entity {
  6. /**
  7. * 公钥
  8. **/
  9. private String publicKey;
  10. /**
  11. * 私钥
  12. **/
  13. private String privateKey;
  14. }

根据RSA算法生成秘钥

  1. /**
  2. * 生成对应的 与我通信的公钥和私钥
  3. * @return
  4. */
  5. public static void createRSAKey(Entity entity) {
  6. try {
  7. // 创建KeyPairGenerator 指定算法为RSA,用于生成对应的公钥和私钥
  8. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  9. // 指定字节长度
  10. keyPairGenerator.initialize(1024);
  11. // 秘钥生成器
  12. KeyPair keyPair = keyPairGenerator.generateKeyPair();
  13. // 公钥
  14. RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
  15. // 进行Base64编码存入
  16. String clientPublicKey = Base64.encodeBase64String(publicKey.getEncoded());
  17. logger.info("生成的clientPublicKey是: {}", clientPublicKey);
  18. entity.setPublicKey(clientPublicKey);
  19. // 私钥
  20. RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
  21. // 进行Base64编码存入
  22. String clientPrivateKey = Base64.encodeBase64String(privateKey.getEncoded());
  23. logger.info("生成的clientPrivateKey是: {}", clientPrivateKey);
  24. entity.setPrivateKey(clientPrivateKey);
  25. } catch (Exception e) {
  26. logger.error("生成秘钥失败");
  27. e.printStackTrace();
  28. }
  29. }

2. 生成数字签名

  1. /**
  2. * 利用私钥信息生成数字签名
  3. * @param data 入参数据body
  4. * @param privateKey 私钥
  5. * @return
  6. */
  7. public static String sign(String data, String privateKey) {
  8. try {
  9. // 入参数据body字节数组
  10. byte[] dataBytes = data.getBytes();
  11. // 获取私钥秘钥字节数组
  12. byte[] keyBytes = Base64.decodeBase64(privateKey);
  13. // 使用给定的编码密钥创建一个新的PKCS8EncodedKeySpec。
  14. // PKCS8EncodedKeySpec 是 PKCS#8标准作为密钥规范管理的编码格式
  15. PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
  16. // 实例化KeyFactory,指定为加密算法 为 RSA
  17. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  18. // 获得PrivateKey对象
  19. PrivateKey privateKey1 = keyFactory.generatePrivate(keySpec);
  20. // 用私钥对信息生成数字签名,指定签名算法为 MD5withRSA
  21. Signature signature = Signature.getInstance("MD5withRSA");
  22. // 初始化签名
  23. signature.initSign(privateKey1);
  24. // 数据body带入
  25. signature.update(dataBytes);
  26. // 对签名进行Base64编码
  27. return Base64.encodeBase64String(signature.sign());
  28. } catch (Exception e) {
  29. e.printStackTrace();
  30. }
  31. return null;
  32. }

3. 校验数字签名

  1. /**
  2. * 利用公钥校验数字签名
  3. * @param data 入参数据body
  4. * @param publicKey 公钥
  5. * @param sign 签名
  6. * @return
  7. */
  8. public static boolean verify(String data, String publicKey, String sign) {
  9. try {
  10. // 入参数据body字节数组
  11. byte[] dataBytes = data.getBytes("UTF-8");
  12. // 获取公钥秘钥字节数组
  13. byte[] keyBytes = Base64.decodeBase64(publicKey);
  14. // 使用给定的编码密钥创建一个新的X509EncodedKeySpec
  15. // X509EncodedKeySpec是基于X.509证书提前的公钥,一种java秘钥规范
  16. X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
  17. // 实例化KeyFactory,指定为加密算法 为 RSA
  18. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  19. // 获取publicKey对象
  20. PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec);
  21. // 用私钥对信息生成数字签名,指定签名算法为 MD5withRSA
  22. Signature signature = Signature.getInstance("MD5withRSA");
  23. // 带入公钥进行验证
  24. signature.initVerify(publicKey1);
  25. // 数据body带入
  26. signature.update(dataBytes);
  27. // 验证签名
  28. return signature.verify(Base64.decodeBase64(sign));
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. return false;
  32. }
  33. }

附完整代码:

  1. package com.example.demo.rsaSecret;
  2. import org.apache.commons.codec.binary.Base64;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import java.security.KeyFactory;
  6. import java.security.KeyPair;
  7. import java.security.KeyPairGenerator;
  8. import java.security.PrivateKey;
  9. import java.security.PublicKey;
  10. import java.security.Signature;
  11. import java.security.interfaces.RSAPrivateKey;
  12. import java.security.interfaces.RSAPublicKey;
  13. import java.security.spec.PKCS8EncodedKeySpec;
  14. import java.security.spec.X509EncodedKeySpec;
  15. /**
  16. * 功能说明: RSA加密解密工具类
  17. */
  18. public class RSAUtil {
  19. private static final Logger logger = LoggerFactory.getLogger(RSAUtil.class);
  20. public static void main(String[] args) {
  21. Entity entity = new Entity();
  22. // 使用RSA算法生成 公钥与私钥, 生成的公私钥 是一一对应的。
  23. createRSAKey(entity);
  24. String body = "123456";
  25. String body2 = "77897";
  26. // 将入参数据以及私钥进行数字加签
  27. String sign = sign(body, entity.getPrivateKey());
  28. // 根据入参数据以及公钥进行验证签名,若入参数据body被修改或者秘钥不正确都会导致验签失败;例如加签使用body,验签使用body2则导致验签失败
  29. boolean verifyFlag = verify(body,entity.getPublicKey(), sign);
  30. if (verifyFlag) {
  31. logger.info("验签成功");
  32. } else {
  33. logger.info("验签失败");
  34. }
  35. }
  36. /**
  37. * 生成对应的 与我通信的公钥和私钥
  38. * @return
  39. */
  40. public static void createRSAKey(Entity entity) {
  41. try {
  42. // 创建KeyPairGenerator 指定算法为RSA,用于生成对应的公钥和私钥
  43. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  44. // 指定字节长度
  45. keyPairGenerator.initialize(1024);
  46. // 秘钥生成器
  47. KeyPair keyPair = keyPairGenerator.generateKeyPair();
  48. // 公钥
  49. RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
  50. // 进行Base64编码存入
  51. String clientPublicKey = Base64.encodeBase64String(publicKey.getEncoded());
  52. logger.info("生成的clientPublicKey是: {}", clientPublicKey);
  53. entity.setPublicKey(clientPublicKey);
  54. // 私钥
  55. RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
  56. // 进行Base64编码存入
  57. String clientPrivateKey = Base64.encodeBase64String(privateKey.getEncoded());
  58. logger.info("生成的clientPrivateKey是: {}", clientPrivateKey);
  59. entity.setPrivateKey(clientPrivateKey);
  60. } catch (Exception e) {
  61. logger.error("生成秘钥失败");
  62. e.printStackTrace();
  63. }
  64. }
  65. /**
  66. * 利用私钥信息生成数字签名
  67. * @param data 入参数据body
  68. * @param privateKey 私钥
  69. * @return
  70. */
  71. public static String sign(String data, String privateKey) {
  72. try {
  73. // 入参数据body字节数组
  74. byte[] dataBytes = data.getBytes();
  75. // 获取私钥秘钥字节数组
  76. byte[] keyBytes = Base64.decodeBase64(privateKey);
  77. // 使用给定的编码密钥创建一个新的PKCS8EncodedKeySpec。
  78. // PKCS8EncodedKeySpec 是 PKCS#8标准作为密钥规范管理的编码格式
  79. PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
  80. // 实例化KeyFactory,指定为加密算法 为 RSA
  81. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  82. // 获得PrivateKey对象
  83. PrivateKey privateKey1 = keyFactory.generatePrivate(keySpec);
  84. // 用私钥对信息生成数字签名,指定签名算法为 MD5withRSA
  85. Signature signature = Signature.getInstance("MD5withRSA");
  86. // 初始化签名
  87. signature.initSign(privateKey1);
  88. // 数据body带入
  89. signature.update(dataBytes);
  90. // 对签名进行Base64编码
  91. return Base64.encodeBase64String(signature.sign());
  92. } catch (Exception e) {
  93. e.printStackTrace();
  94. }
  95. return null;
  96. }
  97. /**
  98. * 利用公钥校验数字签名
  99. * @param data 入参数据body
  100. * @param publicKey 公钥
  101. * @param sign 签名
  102. * @return
  103. */
  104. public static boolean verify(String data, String publicKey, String sign) {
  105. try {
  106. // 入参数据body字节数组
  107. byte[] dataBytes = data.getBytes("UTF-8");
  108. // 获取公钥秘钥字节数组
  109. byte[] keyBytes = Base64.decodeBase64(publicKey);
  110. // 使用给定的编码密钥创建一个新的X509EncodedKeySpec
  111. // X509EncodedKeySpec是基于X.509证书提前的公钥,一种java秘钥规范
  112. X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
  113. // 实例化KeyFactory,指定为加密算法 为 RSA
  114. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  115. // 获取publicKey对象
  116. PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec);
  117. // 用私钥对信息生成数字签名,指定签名算法为 MD5withRSA
  118. Signature signature = Signature.getInstance("MD5withRSA");
  119. // 带入公钥进行验证
  120. signature.initVerify(publicKey1);
  121. // 数据body带入
  122. signature.update(dataBytes);
  123. // 验证签名
  124. return signature.verify(Base64.decodeBase64(sign));
  125. } catch (Exception e) {
  126. e.printStackTrace();
  127. return false;
  128. }
  129. }
  130. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/807054
推荐阅读
相关标签
  

闽ICP备14008679号