在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

常用数字签名算法RSA与DSA的Java程序内实现示例

2016-7-29 15:37| 发布者: zhangjf| 查看: 559| 评论: 0

摘要: RSA加密算法 我们来回顾一下RSA的加密算法。我们从公钥加密算法和签名算法的定义出发,用比较规范的语言来描述这一算法。 RSA公钥加密体制包含如下3个算法:KeyGen(密钥生成算法),Encrypt(加密算法)以及Decryp ...

RSA加密算法
我们来回顾一下RSA的加密算法。我们从公钥加密算法和签名算法的定义出发,用比较规范的语言来描述这一算法。
RSA公钥加密体制包含如下3个算法:KeyGen(密钥生成算法),Encrypt(加密算法)以及Decrypt(解密算法)。
密钥生成算法以安全常数作为输入,输出一个公钥PK,和一个私钥SK。安全常数用于确定这个加密算法的安全性有多高,一般以加密算法使用的质数p的大小有关。越大,质数p一般越大,保证体制有更高的安全性。在RSA中,密钥生成算法如下:算法首先随机产生两个不同大质数p和q,计算N=pq。随后,算法计算欧拉函数。接下来,算法随机选择一个小于的整数e,并计算e关于的模反元素d。最后,公钥为PK=(N, e),私钥为SK=(N, d)。
加密算法以公钥PK和待加密的消息M作为输入,输出密文CT。在RSA中,加密算法如下:算法直接输出密文为
解密算法以私钥SK和密文CT作为输入,输出消息M。在RSA中,解密算法如下:算法直接输出明文为。由于e和d在下互逆,因此我们有:
所以,从算法描述中我们也可以看出:公钥用于对数据进行加密,私钥用于对数据进行解密。当然了,这个也可以很直观的理解:公钥就是公开的密钥,其公开了大家才能用它来加密数据。私钥是私有的密钥,谁有这个密钥才能够解密密文。否则大家都能看到私钥,就都能解密,那不就乱套了。
下面就来看一下Java中的简单实现:

  1. package com.stone.security;
  2. import java.security.KeyPair;
  3. import java.security.KeyPairGenerator;
  4. import java.security.PrivateKey;
  5. import java.security.PublicKey;
  6. import java.util.Arrays;
  7. import javax.crypto.Cipher;
  8. /**
  9. * RSA算法 公钥加密 非对称加密
  10. */
  11. public class RSA {
  12. public static final String KEY_ALGORITHM = "RSA";
  13. public static final String CIPHER_ALGORITHM_ECB1 = "RSA/ECB/PKCS1Padding";
  14. public static final String CIPHER_ALGORITHM_ECB2 = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"; //不能用
  15. public static final String CIPHER_ALGORITHM_ECB3 = "OAEPWithSHA-256AndMGF1Padding"; //不能用
  16. static PublicKey publicKey;
  17. static PrivateKey privateKey;
  18. static Cipher cipher;
  19. static KeyPair keyPair;
  20. public static void main(String[] args) throws Exception {
  21. method1("斯柯达U*(Sfsad7f()*^%%$");
  22. method2("斯柯达U*(Sfsad7f()*^%%$");
  23. method3("斯柯达U*(Sfsad7f()*^%%$");
  24. }
  25. /**
  26. * 公钥加密,私钥解密 使用默认CIPHER_ALGORITHM_ECB1
  27. * @param str
  28. * @throws Exception
  29. */
  30. static void method1(String str) throws Exception {
  31. KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  32. KeyPair keyPair = keyGenerator.generateKeyPair();
  33. publicKey = keyPair.getPublic();
  34. privateKey = keyPair.getPrivate();
  35. cipher = Cipher.getInstance(KEY_ALGORITHM);
  36. cipher.init(Cipher.ENCRYPT_MODE, publicKey); //公钥加密
  37. byte[] encrypt = cipher.doFinal(str.getBytes());
  38. System.out.println("公钥加密后1:" + Arrays.toString(encrypt));
  39. cipher.init(Cipher.DECRYPT_MODE, privateKey);//私钥解密
  40. byte[] decrypt = cipher.doFinal(encrypt);
  41. System.out.println("私钥解密后1:" + new String(decrypt));
  42. }
  43. /**
  44. * 私钥加密,公钥解密 使用默认CIPHER_ALGORITHM_ECB1
  45. * @param str
  46. * @throws Exception
  47. */
  48. static void method2(String str) throws Exception {
  49. KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  50. KeyPair keyPair = keyGenerator.generateKeyPair();
  51. publicKey = keyPair.getPublic();
  52. privateKey = keyPair.getPrivate();
  53. cipher = Cipher.getInstance(KEY_ALGORITHM);
  54. cipher.init(Cipher.ENCRYPT_MODE, privateKey); //私钥加密
  55. byte[] encrypt = cipher.doFinal(str.getBytes());
  56. System.out.println("私钥加密后2:" + Arrays.toString(encrypt));
  57. cipher.init(Cipher.DECRYPT_MODE, publicKey);//公钥解密
  58. byte[] decrypt = cipher.doFinal(encrypt);
  59. System.out.println("公钥解密后2:" + new String(decrypt));
  60. }
  61. /**
  62. * 私钥加密,公钥解密 使用CIPHER_ALGORITHM_ECB1 = RSA/ECB/PKCS1Padding
  63. * @param str
  64. * @throws Exception
  65. */
  66. static void method3(String str) throws Exception {
  67. KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  68. KeyPair keyPair = keyGenerator.generateKeyPair();
  69. publicKey = keyPair.getPublic();
  70. privateKey = keyPair.getPrivate();
  71. cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB1);
  72. cipher.init(Cipher.ENCRYPT_MODE, privateKey); //私钥加密
  73. byte[] encrypt = cipher.doFinal(str.getBytes());
  74. System.out.println("私钥加密后3:" + Arrays.toString(encrypt));
  75. cipher.init(Cipher.DECRYPT_MODE, publicKey);//公钥解密
  76. byte[] decrypt = cipher.doFinal(encrypt);
  77. System.out.println("公钥解密后3:" + new String(decrypt));
  78. }
  79. }
复制代码

DSA算法和数字签名
DSA 一般用于数字签名和认证。
DSA是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。
DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。
在DSA数字签名和认证中,发送者使用自己的私钥对文件或消息进行签名,接受者收到消息后使用发送者的公钥
来验证签名的真实性。DSA只是一种算法,和RSA不同之处在于它不能用作加密和解密,也不能进行密钥交换,
只用于签名,它比RSA要快很多.

  1. package com.stone.security;
  2. import java.security.Key;
  3. import java.security.KeyFactory;
  4. import java.security.KeyPair;
  5. import java.security.KeyPairGenerator;
  6. import java.security.PrivateKey;
  7. import java.security.PublicKey;
  8. import java.security.SecureRandom;
  9. import java.security.Signature;
  10. import java.security.spec.PKCS8EncodedKeySpec;
  11. import java.security.spec.X509EncodedKeySpec;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. import sun.misc.BASE64Decoder;
  15. import sun.misc.BASE64Encoder;
  16. /**
  17. * DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。
  18. * 简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。
  19. * 如果数据和签名不匹配则认为验证失败!即 传输中的数据 可以不再加密,接收方获得数据后,拿到公钥与签名 验证数据是否有效
  20. */
  21. public class DSA {
  22. /**
  23. *不仅可以使用DSA算法,同样也可以使用RSA算法做数字签名
  24. */
  25. public static final String KEY_ALGORITHM = "RSA";
  26. public static final String SIGNATURE_ALGORITHM = "MD5withRSA";*/
  27. public static final String KEY_ALGORITHM = "DSA";
  28. public static final String SIGNATURE_ALGORITHM = "DSA";
  29. public static final String DEFAULT_SEED = "$%^*%^()(HJG8awfjas7"; //默认种子
  30. public static final String PUBLIC_KEY = "DSAPublicKey";
  31. public static final String PRIVATE_KEY = "DSAPrivateKey";
  32. public static void main(String[] args) throws Exception {
  33. String str = "!@#$!#^$#&ZXVDF呆军工路爱着你*()_+";
  34. byte[] data = str.getBytes();
  35. Map<String, Object> keyMap = initKey();// 构建密钥
  36. PublicKey publicKey = (PublicKey) keyMap.get(PUBLIC_KEY);
  37. PrivateKey privateKey = (PrivateKey) keyMap.get(PRIVATE_KEY);
  38. System.out.println("私钥format:" + privateKey.getFormat());
  39. System.out.println("公钥format:" + publicKey.getFormat());
  40. // 产生签名
  41. String sign = sign(data, getPrivateKey(keyMap));
  42. // 验证签名
  43. boolean verify1 = verify("aaa".getBytes(), getPublicKey(keyMap), sign);
  44. System.err.println("经验证 数据和签名匹配:" + verify1);
  45. boolean verify = verify(data, getPublicKey(keyMap), sign);
  46. System.err.println("经验证 数据和签名匹配:" + verify);
  47. }
  48. /**
  49. * 生成密钥
  50. *
  51. * @param seed 种子
  52. * @return 密钥对象
  53. * @throws Exception
  54. */
  55. public static Map<String, Object> initKey(String seed) throws Exception {
  56. System.out.println("生成密钥");
  57. KeyPairGenerator keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  58. SecureRandom secureRandom = new SecureRandom();
  59. secureRandom.setSeed(seed.getBytes());
  60. //Modulus size must range from 512 to 1024 and be a multiple of 64
  61. keygen.initialize(640, secureRandom);
  62. KeyPair keys = keygen.genKeyPair();
  63. PrivateKey privateKey = keys.getPrivate();
  64. PublicKey publicKey = keys.getPublic();
  65. Map<String, Object> map = new HashMap<String, Object>(2);
  66. map.put(PUBLIC_KEY, publicKey);
  67. map.put(PRIVATE_KEY, privateKey);
  68. return map;
  69. }
  70. /**
  71. * 生成默认密钥
  72. *
  73. * @return 密钥对象
  74. * @throws Exception
  75. */
  76. public static Map<String, Object> initKey() throws Exception {
  77. return initKey(DEFAULT_SEED);
  78. }
  79. /**
  80. * 取得私钥
  81. *
  82. * @param keyMap
  83. * @return
  84. * @throws Exception
  85. */
  86. public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
  87. Key key = (Key) keyMap.get(PRIVATE_KEY);
  88. return encryptBASE64(key.getEncoded()); //base64加密私钥
  89. }
  90. /**
  91. * 取得公钥
  92. *
  93. * @param keyMap
  94. * @return
  95. * @throws Exception
  96. */
  97. public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
  98. Key key = (Key) keyMap.get(PUBLIC_KEY);
  99. return encryptBASE64(key.getEncoded()); //base64加密公钥
  100. }
  101. /**
  102. * 用私钥对信息进行数字签名
  103. * @param data 加密数据
  104. * @param privateKey 私钥-base64加密的
  105. * @return
  106. * @throws Exception
  107. */
  108. public static String sign(byte[] data, String privateKey) throws Exception {
  109. System.out.println("用私钥对信息进行数字签名");
  110. byte[] keyBytes = decryptBASE64(privateKey);
  111. PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
  112. KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
  113. PrivateKey priKey = factory.generatePrivate(keySpec);//生成 私钥
  114. //用私钥对信息进行数字签名
  115. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  116. signature.initSign(priKey);
  117. signature.update(data);
  118. return encryptBASE64(signature.sign());
  119. }
  120. /**
  121. * BASE64Encoder 加密
  122. * @param data 要加密的数据
  123. * @return 加密后的字符串
  124. */
  125. private static String encryptBASE64(byte[] data) {
  126. BASE64Encoder encoder = new BASE64Encoder();
  127. String encode = encoder.encode(data);
  128. return encode;
  129. }
  130. /**
  131. * BASE64Decoder 解密
  132. * @param data 要解密的字符串
  133. * @return 解密后的byte[]
  134. * @throws Exception
  135. */
  136. private static byte[] decryptBASE64(String data) throws Exception {
  137. BASE64Decoder decoder = new BASE64Decoder();
  138. byte[] buffer = decoder.decodeBuffer(data);
  139. return buffer;
  140. }
  141. /**
  142. * 校验数字签名
  143. * @param data 加密数据
  144. * @param publicKey
  145. * @param sign 数字签名
  146. * @return
  147. * @throws Exception
  148. */
  149. public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
  150. byte[] keyBytes = decryptBASE64(publicKey);
  151. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  152. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  153. PublicKey pubKey = keyFactory.generatePublic(keySpec);
  154. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  155. signature.initVerify(pubKey);
  156. signature.update(data);
  157. return signature.verify(decryptBASE64(sign)); //验证签名
  158. }
  159. }
复制代码

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-5-6 10:08

Copyright 2015-2025 djqfx

返回顶部