Java实现数字签名

一、数字签名算法概述

   签名认证是对非对称加密技术与数字摘要技术的综合运用,指的是将通信内容的摘要信息使用发送者的私钥进行加密,然后将密文与原文一起传输给信息的接收者,接收者通过发送者的公钥信息来解密被加密的摘要作息,然后使用与发送者相同的摘要算法,对接收到的内容采用相同的方式方式产生摘要串,与解密的摘要串进行对比,如果相同,则说明接收到的内容是完整的,在传输过程中没有受到第三方的篡改,否则说明通信内容已被第三方修改。

   我们知道,每个人都有其特有的私钥,且都是对外界保密的,而通过私钥加密的信息,只能通过其对应的公钥来进行解密。因此,私钥可以代表私钥持有者的身份,可以通过私钥对应的公钥来对私钥拥有者的身份进行校验。通过数字签名,能够确认消息是消息发送方签名并发送过来的,因为其他人根本假冒不了消息发送方的签名,他们没有消息发送者的私钥。而不同的内容,摘要信息千差万别,通过数字摘要算法,可以确保传输内容的完整性,如果传输内容在中途被篡改了,对应的数字签名的值也将发生改变。

数字签名:带有密钥(公钥,私钥)的消息摘要算法。私钥用于签名,公钥用于验证。

数字签名的作用:

   验证数据的完整性,认证数据来源,抗否认。

数字签名实现的具体原理: 
   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.             KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");  
  27.             keyPairGenerator.initialize(512);  
  28.             KeyPair keyPair = keyPairGenerator.generateKeyPair();  
  29.             RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();  
  30.             RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();  
  31.               
  32.             //2.执行签名  
  33.             PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());  
  34.             KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
  35.             PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);  
  36.             Signature signature = Signature.getInstance("MD5withRSA");  
  37.             signature.initSign(privateKey);  
  38.             signature.update(src.getBytes());  
  39.             byte[] result = signature.sign();  
  40.             System.out.println("jdk rsa sign : " + Hex.encodeHexString(result));  
  41.               
  42.             //3.验证签名  
  43.             X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());  
  44.             keyFactory = KeyFactory.getInstance("RSA");  
  45.             PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);  
  46.             signature = Signature.getInstance("MD5withRSA");  
  47.             signature.initVerify(publicKey);  
  48.             signature.update(src.getBytes());  
  49.             boolean bool = signature.verify(result);  
  50.             System.out.println("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.             KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");  
  28.             keyPairGenerator.initialize(512);  
  29.             KeyPair keyPair = keyPairGenerator.generateKeyPair();  
  30.             DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();  
  31.             DSAPrivateKey dsaPrivateKey = (DSAPrivateKey)keyPair.getPrivate();  
  32.               
  33.             //2.执行签名  
  34.             PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());  
  35.             KeyFactory keyFactory = KeyFactory.getInstance("DSA");  
  36.             PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);  
  37.             Signature signature = Signature.getInstance("SHA1withDSA");  
  38.             signature.initSign(privateKey);  
  39.             signature.update(src.getBytes());  
  40.             byte[] result = signature.sign();  
  41.             System.out.println("jdk dsa sign : " + Hex.encodeHexString(result));  
  42.               
  43.             //3.验证签名  
  44.             X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey.getEncoded());  
  45.             keyFactory = KeyFactory.getInstance("DSA");  
  46.             PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);  
  47.             signature = Signature.getInstance("SHA1withDSA");  
  48.             signature.initVerify(publicKey);  
  49.             signature.update(src.getBytes());  
  50.             boolean bool = signature.verify(result);  
  51.             System.out.println("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.             KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");  
  29.             keyPairGenerator.initialize(256);  
  30.             KeyPair keyPair = keyPairGenerator.generateKeyPair();  
  31.             ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic();  
  32.             ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate();  
  33.               
  34.             //2.执行签名  
  35.             PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());  
  36.             KeyFactory keyFactory = KeyFactory.getInstance("EC");  
  37.             PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);  
  38.             Signature signature = Signature.getInstance("SHA1withECDSA");  
  39.             signature.initSign(privateKey);  
  40.             signature.update(src.getBytes());  
  41.             byte[] result = signature.sign();  
  42.             System.out.println("jdk ecdsa sign : " + Hex.encodeHexString(result));  
  43.               
  44.             //3.验证签名  
  45.             X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(ecPublicKey.getEncoded());  
  46.             keyFactory = KeyFactory.getInstance("EC");  
  47.             PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);  
  48.             signature = Signature.getInstance("SHA1withECDSA");  
  49.             signature.initVerify(publicKey);  
  50.             signature.update(src.getBytes());  
  51.             boolean bool = signature.verify(result);  
  52.             System.out.println("jdk ecdsa verify : " + bool);  
  53.         } catch (Exception e) {  
  54.             e.printStackTrace();  
  55.         }  
  56.           
  57.     }  
  58.   
  59. }  
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值