一、概念
数字信封是将对称密钥通过非对称加密(即:有公钥和私钥两个)的结果分发对称密钥的方法。数字信封是实现信息保密性验证的技术。
二、过程描述
在数字信封中,信息发送方采用对称密钥来加密信息内容,然后将此对称密钥用接收方的公开密钥来加密(这部分称数字信封)之后,将它和加密后的信息一起发送给接收方,接收方先用相应的私有密钥打开数字信封,得到对称密钥,然后使用对称密钥解开加密信息。这种技术的安全性相当高。数字信封主要包括数字信封打包和数字信封拆解,数字信封打包是使用对方的公钥将加密密钥进行加密的过程,只有对方的私钥才能将加密后的数据(通信密钥)还原;数字信封拆解是使用私钥将加密过的数据解密的过程。
三、图解
四、代码示例
a.引入依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.69</version>
</dependency>
b.代码
import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import java.io.Serializable;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
* @Author 乐hh
* @Description 数字信封测试
**/
public class EnvelopeTest {
public static void main(String[] args) {
// 1.接收方生成一对公私钥(使用国密算法SM2)
SM2 sm2 = SmUtil.sm2();
PublicKey publicKey = sm2.getPublicKey(); // 公钥用于发送方加密
PrivateKey privateKey = sm2.getPrivateKey(); // 私钥用于接收方解密
// 2.发送方使用接收方的公钥生成数字信封
Envelope envelope = generateEnvelope(publicKey);
// 3.接收方使用私钥解密数字信封
String message = openEnvelope(privateKey, envelope);
System.out.println("信件内容:" + message);
}
/**
* 生成数字信封
*
* @param publicKey SM2公钥
* @return 数字信封
*/
private static Envelope generateEnvelope(PublicKey publicKey) {
// 信件内容
final String message = "Hello world!";
// 使用对称密钥加密信件内容(使用国密算法SM4)
SM4 sm4 = SmUtil.sm4();
byte[] key = sm4.getSecretKey().getEncoded();
String messageCipher = sm4.encryptBase64(message);
// 使用公钥加密对称密钥
SM2 sm2 = new SM2(null, publicKey);
String keyCipher = sm2.encryptBase64(key, KeyType.PublicKey);
return new Envelope(messageCipher, keyCipher);
}
/**
* 打开数字信封
*
* @param privateKey SM2私钥
* @param envelope 数字信封
* @return 信封内容
*/
private static String openEnvelope(PrivateKey privateKey, Envelope envelope) {
// 使用私钥解密得到对称密钥
SM2 sm2 = new SM2(privateKey, null);
byte[] key = sm2.decrypt(Base64Decoder.decode(envelope.getKeyCipher()), KeyType.PrivateKey);
// 使用对称密钥解密得到信件内容
SM4 sm4 = new SM4(key);
byte[] message = sm4.decrypt(Base64Decoder.decode(envelope.getMessageCipher()));
return new String(message);
}
static class Envelope implements Serializable {
/**
* 信件内容密文(Base64编码)
*/
private String messageCipher;
/**
* 对称密钥密文(Base64编码)
*/
private String keyCipher;
public Envelope(String messageCipher, String keyCipher) {
this.messageCipher = messageCipher;
this.keyCipher = keyCipher;
}
public String getMessageCipher() {
return messageCipher;
}
public void setMessageCipher(String messageCipher) {
this.messageCipher = messageCipher;
}
public String getKeyCipher() {
return keyCipher;
}
public void setKeyCipher(String keyCipher) {
this.keyCipher = keyCipher;
}
}
}
c.运行结果