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