数字签名的原理图解,广泛使用的数字签名方法

首页 > 教育 > 作者:YD1662024-05-02 12:49:58

数字签名的工作原理

1、Alice(密码学中常用A到Z开头的人名代替甲乙丙丁等,字母越靠后出现频率越低)生成一对密钥,一个是sk(signing key),是非公开的;另一个是vk(verification key),是公开的。

这一对密钥同时生成,并且在数学上是相互关联的,同时,根据vk无法推测出关于sk的任何信息。

2、数字签名算法接收两个输出:信息M和sk,生成一个数字签名Sm。

3、验证函数接收信息M、Sm以及vk作为输入,返回结果是yes或者no。这一步的目的是为了验证你看到的针对信息M的数字签名确实是由Alice的sk来签发的,用于确认信息与签名是否相符。

与手写签名不同,手写签名基本都是相似的,但是数字签名却受输入影响很大。对输入轻微的改变都会产生一个完全不同的数字签名。一般不会对信息直接进行数字签名,而是对信息的哈希值进行签名。由加密哈希函数的无碰撞性可知,这样和对原信息进行签名一样安全。

数字签名的原理图解,广泛使用的数字签名方法(1)

数字签名实现的具体原理:

1、将报文按双方约定的HASH算法计算得到一个固定位数的报文摘要。

在数学上保证,只要改动报文中任何一位,重新计算出的报文摘要值就会与原先的值不相符。这样就保证了报文的不可更改性。(详见参考资料的"公钥密码技术原理"章节)

2、将该报文摘要值用发送者的私人密钥加密,然后连同原报文和数字证书(包含公钥)一起发送给接收者而产生的报文即称数字签名。

3、接收方收到数字签名后,用同样的HASH算法对报文计算摘要值,然后与用发送者的公开密钥进行解密解开的报文摘要值相比较,如相等则说明报文确实来自所称的发送者。

4、同时通过证书颁发机构CA确认证书的有效性即可确认发送的真实身份。

代码案例(包含签名和验签代码块):

import java.security.PublicKey; import java.security.cert.X509Certificate; public class CertificateCoderDemo { public static void main(String[] args) { String keyStorePath = "c:/server.jks"; String alias = "server"; String pwd = "123456"; String cerPath = "c:/server.cer"; // 1、根据keyStore路径获取证书 try { X509Certificate x509 = (X509Certificate) CertificateCoder.getCertificate(keyStorePath, alias, pwd); System.out.println("证书内容:\r\n" x509); } catch (Exception e) { e.printStackTrace(); } // 2、根据cert路径获取公钥 try { PublicKey publicKey = CertificateCoder.getPublicKeyByCertificate(cerPath); System.out.println("公钥内容:\r\n" publicKey); } catch (Exception e) { e.printStackTrace(); } // 3、私钥加密公钥解密; String data = "[私钥加密公钥解密]"; try { byte[] decryptData = CertificateCoder.encryptByPrivateKey(data.getBytes(), keyStorePath, alias, pwd); System.out.println("私钥加密内容:" decryptData); byte[] encryptData = CertificateCoder.decryptByPublicKey(decryptData, cerPath); System.out.println("公钥加密内容:" new String(decryptData)); } catch (Exception e) { e.printStackTrace(); } // 4、公钥加密公钥解密; String text = "[公钥加密私钥解密]"; try { byte[] decryptData = CertificateCoder.encryptByPublicKey(text.getBytes(), cerPath); System.out.println("公钥加密内容:" decryptData); byte[] encryptData = CertificateCoder.decryptByPrivateKey(decryptData, keyStorePath, alias, pwd); System.out.println("私钥加密内容:" new String(encryptData)); } catch (Exception e) { e.printStackTrace(); } // 5、证书签名(私钥签名) String signData = "证书签名(私钥签名)"; byte[] signedData = null; try { signedData = CertificateCoder.sign(signData.getBytes(), keyStorePath, pwd, alias); System.out.println("证书签名结果:" signedData); } catch (Exception e) { e.printStackTrace(); } // 6、验签(公钥验签) try { boolean verifyResult = CertificateCoder.verify(signData.getBytes(), signedData, cerPath); System.out.println("证书验签结果:" verifyResult); } catch (Exception e) { e.printStackTrace(); } } }

import javax.crypto.Cipher; import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; public class CertificateCoder { public static final String CERT_TYPE = "X.509"; /** * 获取私匙 * * @param keyStorePath * @param pwd * @param alias * @return PrivateKey 私匙 * @throws Exception */ private static PrivateKey getPrivateKey(String keyStorePath, String pwd, String alias) throws Exception { KeyStore ks = getKeyStore(keyStorePath, pwd); return (PrivateKey) ks.getKey(alias, pwd.toCharArray()); } /** * @param keyStorePath * @param pwd * @return keyStore 密匙库 * @throws Exception */ private static KeyStore getKeyStore(String keyStorePath, String pwd) throws Exception { KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); FileInputStream in = new FileInputStream(keyStorePath); ks.load(in, pwd.toCharArray()); in.close(); return ks; } /** * @param certificatePath * @return Certificate 证书 * @throws Exception */ private static Certificate getCertificate(String certificatePath) throws Exception { CertificateFactory factory = CertificateFactory.getInstance(CERT_TYPE); FileInputStream in = new FileInputStream(certificatePath); Certificate certificate = factory.generateCertificate(in); in.close(); return certificate; } /** * 通过证书返回公匙 * * @param certificatePath * @return Publickey 返回公匙 * @throws Exception */ public static PublicKey getPublicKeyByCertificate(String certificatePath) throws Exception { Certificate certificate = getCertificate(certificatePath); return certificate.getPublicKey(); } /** * @param keyStorePath * @param alias * @param pwd * @return Certificate 证书 * @throws Exception */ public static Certificate getCertificate(String keyStorePath, String alias, String pwd) throws Exception { KeyStore ks = getKeyStore(keyStorePath, pwd); //获取证书 return ks.getCertificate(alias); } /** * 私匙加密 * * @param data * @param keyStorePath * @param alias * @param pwd * @return byte[] 被私匙加密的数据 * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String keyStorePath, String alias, String pwd) throws Exception { PrivateKey privateKey = getPrivateKey(keyStorePath, pwd, alias); //对数据进行加密 Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 私匙解密 * * @param data * @param keyStorePath * @param alias * @param pwd * @return byte[] 私匙解密的数据 * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] data, String keyStorePath, String alias, String pwd) throws Exception { PrivateKey privateKey = getPrivateKey(keyStorePath, pwd, alias); Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 公匙加密 * * @param data * @param cerPath * @return byte[] 被公匙加密的数据 * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, String cerPath) throws Exception { //获取公匙 PublicKey publicKey = getPublicKeyByCertificate(cerPath); System.out.println(publicKey.getAlgorithm()); Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 公匙解密 * * @param data * @param cerPath * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] data, String cerPath) throws Exception { PublicKey publicKey = getPublicKeyByCertificate(cerPath); Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 签名 * * @param sign * @param keyStorePath * @param pwd * @param alias * @return * @throws Exception */ public static byte[] sign(byte[] sign, String keyStorePath, String pwd, String alias) throws Exception { //获取证书 X509Certificate x509 = (X509Certificate) getCertificate(keyStorePath, alias, pwd); //构建签名,由证书指定签名算法 Signature sa = Signature.getInstance(x509.getSigAlgName()); //获取私匙 PrivateKey privateKey = getPrivateKey(keyStorePath, pwd, alias); sa.initSign(privateKey); sa.update(sign); return sa.sign(); } /** * 验证签名 * * @param data * @param sign * @param cerPath * @return * @throws Exception */ public static boolean verify(byte[] data, byte[] sign, String cerPath) throws Exception { X509Certificate x509 = (X509Certificate) getCertificate(cerPath); Signature sa = Signature.getInstance(x509.getSigAlgName()); sa.initVerify(x509); sa.update(data); return sa.verify(sign); } }

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.