• Java实现基于RSA的数字签名


    加密与数字签名的区别

    1、加密保证了数据接受方的数据安全性。加密的作用是防止泄密。

    2、签名保证了数据发送方的数据安全性。签名的作用是防止篡改。

    数字签名的应用

    问题:在比特币中,怎么证明这个交易是你发布的?

    这是就需要用到数字签名,数字签名大概可已描述为:用私钥加密,用公钥解密。发布一条交易信息:“我给xxx转了0.2个比特币”,将这条消息用自己的私钥加密,再发布出去,大众在收到这条消息后,用我的公钥验签,验证成功则说明是我发布的交易。

    签名的过程与加密相反。

    代码

    1. package RSA;
    2. import org.apache.commons.codec.binary.Base64;
    3. import java.io.BufferedReader;
    4. import java.io.FileReader;
    5. import java.security.*;
    6. import java.security.interfaces.RSAPrivateKey;
    7. import java.security.interfaces.RSAPublicKey;
    8. import java.security.spec.PKCS8EncodedKeySpec;
    9. import java.security.spec.X509EncodedKeySpec;
    10. import java.util.HashMap;
    11. import java.util.Map;
    12. /**
    13. * @author WuYongheng
    14. * @date 2022/11/22
    15. * @description 数字签名 RSA
    16. */
    17. public class RsaSignature {
    18. //数字签名 - 签名验证算法
    19. private static final String SIGNATRUE_ALGORITHM = "MD5withRSA";
    20. //数字签名 - RSA算法
    21. private static final String KEY_ALGORITHM = "RSA";
    22. //私钥
    23. private static final String PRIVATEKEY = "RSAPrivateKey";
    24. //公钥
    25. private static final String PUBLICKEY = "RSAPublicKey";
    26. /**
    27. * RSA长度
    28. * 默认是 1024
    29. * 必须是 64的倍数
    30. * 范围:512 - 65536
    31. */
    32. private static final int KeySize = 512; // 512 位 2进制,128 位 16进制
    33. /**
    34. * 初始化
    35. *
    36. * @return map
    37. * @throws Exception
    38. */
    39. public static Map initKey() throws Exception {
    40. //实例化,生成器
    41. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
    42. //初始化
    43. keyPairGenerator.initialize(KeySize);
    44. //获取公私钥对
    45. KeyPair keyPair = keyPairGenerator.generateKeyPair();
    46. //获取私钥
    47. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    48. //获取公钥
    49. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    50. Map map = new HashMap();
    51. map.put(PRIVATEKEY, privateKey);
    52. map.put(PUBLICKEY, publicKey);
    53. return map;
    54. }
    55. /**
    56. * 取得公钥
    57. *
    58. * @param map
    59. * @return byte[]
    60. */
    61. public static byte[] getPublicKey(Map map) {
    62. PublicKey publicKey = (PublicKey) map.get(PUBLICKEY);
    63. return publicKey.getEncoded();
    64. }
    65. /**
    66. * 取得私钥
    67. *
    68. * @param map
    69. * @return byte[]
    70. */
    71. public static byte[] getPrivateKey(Map map) {
    72. PrivateKey privateKey = (PrivateKey) map.get(PRIVATEKEY);
    73. return privateKey.getEncoded();
    74. }
    75. /**
    76. * 私钥加密
    77. *
    78. * @param source 数据
    79. * @param key 私钥
    80. * @return 签名
    81. * @throws Exception
    82. */
    83. public static String sign(String source, byte[] key) throws Exception {
    84. byte[] data = source.getBytes("utf-8");
    85. // 取得私钥
    86. PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
    87. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    88. // 生成私钥
    89. PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    90. //新增: 实例化 签名对象
    91. Signature signature = Signature.getInstance(SIGNATRUE_ALGORITHM);
    92. //初始化 私钥
    93. signature.initSign(privateKey);
    94. //更新签名
    95. signature.update(data);
    96. byte[] enSign = signature.sign();
    97. return Base64.encodeBase64String(enSign);
    98. }
    99. /**
    100. * 校验
    101. *
    102. * @param source 源数据
    103. * @param key 公钥
    104. * @param signStr 已签名的数据
    105. * @return true or false
    106. * @throws Exception
    107. */
    108. public static boolean verify(String source, byte[] key, String signStr) throws Exception {
    109. // 还原即将 解密的 数据源
    110. byte[] data = source.getBytes("utf-8");
    111. // 还原已签名数据
    112. byte[] signData = Base64.decodeBase64(signStr);
    113. // 取得公钥
    114. X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
    115. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    116. // 生成公钥
    117. PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
    118. //新增: 实例化 签名对象
    119. Signature signature = Signature.getInstance(SIGNATRUE_ALGORITHM);
    120. //初始化 校验公钥
    121. signature.initVerify(publicKey);
    122. //更新签名
    123. signature.update(data);
    124. //验证
    125. return signature.verify(signData);
    126. }
    127. public static void main(String[] args) throws Exception {
    128. Map keyMap = initKey();
    129. byte[] privateKey = getPrivateKey(keyMap);
    130. byte[] publicKey = getPublicKey(keyMap);
    131. System.out.println("获取的私钥:" + Base64.encodeBase64String(privateKey));
    132. System.out.println("获取的公钥:" + Base64.encodeBase64String(publicKey));
    133. String source = "";
    134. //需要签名文件的内容
    135. String fileName = "D:\\code\\aaa.txt";
    136. try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
    137. String line;
    138. while ((line = br.readLine()) != null) {
    139. System.out.println("文件内容是: " + line);
    140. source = line;
    141. }
    142. }
    143. System.out.println("需要签名的文件内容是: " + source);
    144. String sign = sign(source, privateKey);
    145. System.out.println("签名后:" + sign);
    146. boolean flat = verify(source, publicKey, sign);
    147. System.out.println("校验结果:" + flat);
    148. }
    149. }

    效果

  • 相关阅读:
    【Vue】Vue的Mustache插值语法、v-bind指令
    linux 网络 sk_buff结构
    ES6中的原型对象
    进公司第一天 git流程
    使用Java拓展本地开源大模型的网络搜索问答能力
    (1)多线程-线程的创建
    手动部署 OceanBase 集群
    基于uniapp框架的古汉语学习考试系统 微信小程序python+java+node.js+php
    锐龙r5 6600u和r5 5600u区别 r56600u和r55600u对比
    Rust Bevy 实体组件系统
  • 原文地址:https://blog.csdn.net/Ipkiss_Yongheng/article/details/127986061