一、数字签名算法概述
签名认证是对非对称加密技术与数字摘要技术的综合运用,指的是将通信内容的摘要信息使用发送者的私钥进行加密,然后将密文与原文一起传输给信息的接收者,接收者通过发送者的公钥信息来解密被加密的摘要作息,然后使用与发送者相同的摘要算法,对接收到的内容采用相同的方式方式产生摘要串,与解密的摘要串进行对比,如果相同,则说明接收到的内容是完整的,在传输过程中没有受到第三方的篡改,否则说明通信内容已被第三方修改。
我们知道,每个人都有其特有的私钥,且都是对外界保密的,而通过私钥加密的信息,只能通过其对应的公钥来进行解密。因此,私钥可以代表私钥持有者的身份,可以通过私钥对应的公钥来对私钥拥有者的身份进行校验。通过数字签名,能够确认消息是消息发送方签名并发送过来的,因为其他人根本假冒不了消息发送方的签名,他们没有消息发送者的私钥。而不同的内容,摘要信息千差万别,通过数字摘要算法,可以确保传输内容的完整性,如果传输内容在中途被篡改了,对应的数字签名的值也将发生改变。
数字签名:带有密钥(公钥,私钥)的消息摘要算法。私钥用于签名,公钥用于验证。
数字签名的作用:
验证数据的完整性,认证数据来源,抗否认。
数字签名实现的具体原理:
1、 将报文按双方约定的HASH算法计算得到一个固定位数的报文摘要。在数学上保证,只要改动报文中任何一位,重新计算出的报文摘要值就会与原先的值不相符。这样就保证了报文的不可更改性。(详见参考资料的"公钥密码技术原理"章节)
2、 将该报文摘要值用发送者的私人密钥加密,然后连同原报文和数字证书(包含公钥)一起发送给接收者而产生的报文即称数字签名。
3、接收方收到数字签名后,用同样的HASH算法对报文计算摘要值,然后与用发送者的公开密钥进行解密解开的报文摘要值相比较,如相等则说明报文确实来自所称的发送者。
4、同时通过证书颁发机构CA确认证书的有效性即可确认发送的真实身份。
数字签名的产生过程如图如示:
数字签名的校验过程:
常用的数字签名有:RSA、DSA、ECDSA
二、数字签名算法—RSA
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
特性:安全性抗和否认性
主要包括两类:MD、SHA
具体算法如下图:
例子:
[java] view plain copy
1. package rmd_intl_app.Test;
2. import java.security.KeyFactory;
3. import java.security.KeyPair;
4. import java.security.KeyPairGenerator;
5. import java.security.PrivateKey;
6. import java.security.PublicKey;
7. import java.security.Signature;
8. import java.security.interfaces.RSAPrivateKey;
9. import java.security.interfaces.RSAPublicKey;
10. import java.security.spec.PKCS8EncodedKeySpec;
11. import java.security.spec.X509EncodedKeySpec;
12.
13. import org.apache.commons.codec.binary.Hex;
14.
15. public class ImoocRSA {
16.
17. private static String src = "imooc security rsa";
18.
19. public static void main(String[] args) {
20. jdkRSA();
21. }
22.
23. public static void jdkRSA() {
24. try {
25. //1.初始化密钥
26. "RSA");
27. 512);
28. KeyPair keyPair = keyPairGenerator.generateKeyPair();
29. RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
30. RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
31.
32. //2.执行签名
33. new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
34. "RSA");
35. PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
36. "MD5withRSA");
37. signature.initSign(privateKey);
38. signature.update(src.getBytes());
39. byte[] result = signature.sign();
40. "jdk rsa sign : " + Hex.encodeHexString(result));
41.
42. //3.验证签名
43. new X509EncodedKeySpec(rsaPublicKey.getEncoded());
44. "RSA");
45. PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
46. "MD5withRSA");
47. signature.initVerify(publicKey);
48. signature.update(src.getBytes());
49. boolean bool = signature.verify(result);
50. "jdk rsa verify : " + bool);
51. catch (Exception e) {
52. e.printStackTrace();
53. }
54. }
55.
56. }
三、数字签名算法—DSA
DSA是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSfS(DigitalSignature Standard)。
DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。DSA的一个重要特点是两个素数公开,这样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA却做不到。
DSA仅包含数字签名
具体算法如下图:
例子:
[java] view plain copy
1. package com.imooc.security.dsa;
2.
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.Signature;
9. import java.security.interfaces.DSAPrivateKey;
10. import java.security.interfaces.DSAPublicKey;
11. import java.security.spec.PKCS8EncodedKeySpec;
12. import java.security.spec.X509EncodedKeySpec;
13.
14. import org.apache.commons.codec.binary.Hex;
15.
16. public class ImoocDSA {
17.
18. private static String src = "imooc security dsa";
19.
20. public static void main(String[] args) {
21. jdkDSA();
22. }
23.
24. public static void jdkDSA() {
25. try {
26. //1.初始化密钥
27. "DSA");
28. 512);
29. KeyPair keyPair = keyPairGenerator.generateKeyPair();
30. DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();
31. DSAPrivateKey dsaPrivateKey = (DSAPrivateKey)keyPair.getPrivate();
32.
33. //2.执行签名
34. new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());
35. "DSA");
36. PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
37. "SHA1withDSA");
38. signature.initSign(privateKey);
39. signature.update(src.getBytes());
40. byte[] result = signature.sign();
41. "jdk dsa sign : " + Hex.encodeHexString(result));
42.
43. //3.验证签名
44. new X509EncodedKeySpec(dsaPublicKey.getEncoded());
45. "DSA");
46. PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
47. "SHA1withDSA");
48. signature.initVerify(publicKey);
49. signature.update(src.getBytes());
50. boolean bool = signature.verify(result);
51. "jdk dsa verify : " + bool);
52. catch (Exception e) {
53. e.printStackTrace();
54. }
55. }
56.
57. }
四、数字签名算法—ECDSA
ECDSA: 椭圆曲线数字签名算法(Elliptic Curve Digital Signatrue Algorithm)
特点:速度快,强度高,签名短
具体算法如下图:
例子:
[java] view plain copy
1. package com.imooc.security.ecdsa;
2.
3. import java.security.KeyFactory;
4. import java.security.KeyPair;
5. import java.security.KeyPairGenerator;
6. import java.security.NoSuchAlgorithmException;
7. import java.security.PrivateKey;
8. import java.security.PublicKey;
9. import java.security.Signature;
10. import java.security.interfaces.ECPrivateKey;
11. import java.security.interfaces.ECPublicKey;
12. import java.security.spec.PKCS8EncodedKeySpec;
13. import java.security.spec.X509EncodedKeySpec;
14.
15. import org.apache.commons.codec.binary.Hex;
16.
17. public class ImoocECDSA {
18.
19. private static String src = "imooc security ecdsa";
20.
21. public static void main(String[] args) {
22. jdkECDSA();
23. }
24.
25. public static void jdkECDSA() {
26. try {
27. //1.初始化密钥
28. "EC");
29. 256);
30. KeyPair keyPair = keyPairGenerator.generateKeyPair();
31. ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic();
32. ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate();
33.
34. //2.执行签名
35. new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
36. "EC");
37. PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
38. "SHA1withECDSA");
39. signature.initSign(privateKey);
40. signature.update(src.getBytes());
41. byte[] result = signature.sign();
42. "jdk ecdsa sign : " + Hex.encodeHexString(result));
43.
44. //3.验证签名
45. new X509EncodedKeySpec(ecPublicKey.getEncoded());
46. "EC");
47. PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
48. "SHA1withECDSA");
49. signature.initVerify(publicKey);
50. signature.update(src.getBytes());
51. boolean bool = signature.verify(result);
52. "jdk ecdsa verify : " + bool);
53. catch (Exception e) {
54. e.printStackTrace();
55. }
56.
57. }
58.
59. }
60.