p7数字信封

PKCS7的数字信封格式分为两种:带签名的数字信封和不带签名的数字信封。由于这个数字信封的生成过程比较复杂,所以这两种格式比较容易记混,导致都搞不清楚一个数字信封里面到底是存储的什么内容了。下面我就详细的解释一下,这两种数字信封的生成过程和其详细的数据结构。

不带签名的数字信封:
不带签名的数字信封内容类型由任意类型的加密内容和加密的一个/多个接收者的内容加密密钥组成,其生成过程如下:
1. 发送方随机产生一个对应于特定加密内容加密密钥。
2. 发送方将内容加密密钥用每个接收者的公钥加密。
3. 对于每一个接收者,把加了密的内容加密密钥和接收者的其他信息放入RecipientInfo值中。
4. 用内容加密密钥加密内容。
5. 将所有接收者的RecipientInfo值和加了密的内容放入EnvelopedData值中。

发送给接收方后,解包的过程很简单:接收者用自己的私钥解开加密的内容加密密钥,然后用该密钥解密密文内容。整个过程参与非对称运算的只有接收方的密钥对。

带签名的数字信封:
带签名的数字信封由任意类型的加密内容、加了密的一个/多个接收者的内容加密密钥和双重加密的一个/多个签名者的消息摘要。“双重加密”由签名者私钥的加密和内容加密密钥的加密组成。其生成过程如下:

1.发送方随机产生一个对应于特定加密算法的内容加密密钥。
2. 发送方将内容加密密钥用每个接收者的公钥加密。
3. 对于每一个接收者,把加了密的内容加密密钥和接收者的其他信息放入RecipientInfo值中,参见数据结构2。
4. 对于每一个签名者,他用自己的消息摘要算法计算出摘要值 (如果两个签名者使用同样的算法,那么摘要值只需计算一次) 。
5. 对于每一个签名者,消息摘要和相关的信息用自己的私钥加密,结果再用内容加密密钥加密。
6. 对于每一个签名者,把双重加密(即第5步中的先非对称加密,再对称加密的过程)的消息摘要和其他的签名者特定信息放入SignerInfo 值中。
7. 用内容加密密钥加密内容。
8. 把所有签名者的消息摘要算法、所有签名者的SignerInfo值、所有接收者的RecipientInfo值和加了密的内容一起放入SignedAndEnvelopedData 值中。

接收方接到数字信封后,解封操作会复杂些:
1.收方B接受到数字信封DE后,首先用自己的私钥PVB解密数字信封,取出对称密钥SK;2.收方B用对称密钥SK通过DES算法解密加密信息E,还原出原文信息、数字签名SD及发方A证书的公钥PBA;3. 收方B验证数字签名,先用发方A的公钥解密数字签名得数字摘要MD;4.收方B同时将原文信息用同样的哈希运算,求得一个新的数字摘要MD’;5.将两个数字摘要MD和MD’进行比较,验证原文是否被修改。如果二者相等,说明数据没有被篡改,是保密传输的,签名是真实的;否则拒绝该签名。

下图为简单流程:

代码示例:

/**
	 * @param publicKey 公钥对象
	 * @param orgData  原文
	 * @return Result if(code== 200)success else fail   
	 * encryptFileStr 加密后的字符串
	 * encryptKeyStr  加密后的秘钥字符串
	 * @throws UnsupportedEncodingException 
	 * @throws NoSuchProviderException 
	 * @throws NoSuchAlgorithmException 
	 */
	public static Result strEncrypt(PublicKey publicKey,String orgData) throws UnsupportedEncodingException {
		try {
			//创建对称秘钥对
			byte[] key = Sm4Utils.generateKey();
			//对加密
			byte[] fileEncryptBytes = Sm4Utils.encrypt_ECB_Padding(key, orgData.getBytes(charset));
			//对秘钥对加密
			byte[] encryptKey = SM2Util.encrypt((BCECPublicKey)publicKey, key);
			//将返回值base64加密
			String encryptDataStr = Base64Utils.encode(fileEncryptBytes);
			String encryptKeyStr = Base64Utils.encode(encryptKey);
			return new Result(Result.CODE_SUCCESS,"加密成功", encryptDataStr,encryptKeyStr);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return new Result(Result.CODE_EXCEPTION, "NoSuchAlgorithmException,没有找到该摘要算法");
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
			return new Result(Result.CODE_EXCEPTION, "NoSuchProviderException,没有找到该加密机");
		}catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | InvalidCipherTextException e ) {
			e.printStackTrace();
			return new Result(Result.CODE_EXCEPTION, "加密失败:"+e.getMessage());
		}
	}

 参考:

https://blog.csdn.net/weixin_39636696/article/details/115780593

https://gitee.com/saxonkiku/encrypt_and_decrypt_file/blob/master/src/main/java/com/ymwk/StrEncrypt.java

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值