关于SM4填充算法PKCS5和PKCS7讲解

前言:

  今天刚好在系统上增加SM4算法的支持,SM4算法的实现网上你可以搜到很多版本,但是如果你要运用到实际中时,你一定要了解SM4算法填充规则。

正文:

  首先,SM4接口大多是以最小单位16Byte进行加解密。因此SM4的密文长度通常是16Byte的倍数。当你待加密数据小于16Byte时,你便需要使用填充算法。

PKCS7填充算法规则:

 PKCS7填充单位为16Byte,对于不满16Byte的数据,以【16-数据长度】字符进行填充。其实现算法如下:

int PKCS7(unsigned char *pucData, unsigned long ulDataLen, unsigned char pucPaddingData[16])
{
	unsigned char pucPadding = 0;
	
	if(ulDataLen > 16)
	{
		return -1;
	}
	pucPadding = 16 - ulDataLen;
	
	memcpy(pucPaddingData, pucData, ulDataLen);
	memset(pucPaddingData + ulDataLen, pucPadding, 16 - ulDataLen);
	return 0;
}

PKCS5填充算法规则:

 PKCS5属于PKCS7填充单位为8Byte,对于不满8Byte的数据,以【8-数据长度】字符进行填充。其实现算法如下:

int PKCS5(unsigned char *pucData, unsigned long ulDataLen, unsigned char pucPaddingData[8])
{
	unsigned char pucPadding = 0;
	
	if(ulDataLen > 8)
	{
		return -1;
	}
	pucPadding = 8 - ulDataLen;
	
	memcpy(pucPaddingData, pucData, ulDataLen);
	memset(pucPaddingData + ulDataLen, pucPadding, 8 - ulDataLen);
	return 0;
}

注意事项:

1、如果你使用的是SM4算法,你直接使用PKCS7填充即可,之前我遇到过JAVA的API里写着使用PKCS5,但实际输出结果为PKCS7。

2、如果你使用了填充算法加密数据,如果是PKCS7算法,则待加密数据为16倍数时,待加密数据尾部需要补16位0x10。

3、如果你使用了填充算法加密数据,如果是PKCS5算法,则待加密数据为8倍数时,待加密数据尾部需要补8位0x8。

4、同理解密时,如果确定加密时使用了填充算法,对于解密后的数据,需要将填充数据剔除。

 

### SM4 加密算法在 CBC 模式下的 PKCS5Padding PKCS7Padding 填充方式比较 #### 数据填充机制概述 数据加密过程中,当明文长度不是分组大小的整数倍时,需要对最后一个不完整的分组进行填充PKCS5Padding PKCS7Padding 是两种常见的填充方案。 #### PKCS5Padding 特点 PKCS5Padding 主要用于 DES、AES 等 8 字节分组密码算法。该方法规定如果最后一块不足 8 字节,则用相同的字节数来填补剩余空间[^2]。例如: - 如果最后剩下 3 字节未填满,则补充 5 个 `0x05`; - 若正好为 8 的倍数,则额外增加一整个新的全为 `0x08` 的区块作为填充。 ```java // Java 中使用 PKCS5Padding 进行填充的例子 Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding"); SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "SM4"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); byte[] encryptedData = cipher.doFinal(plainText.getBytes()); ``` #### PKCS7Padding 特点 PKCS7Padding 更具通用性,适用于任意长度的分组密码。对于每个可能的数据单元尺寸(通常指一个字节),它会向消息结尾追加若干个相同数值的字节直到达到所需边界条件;这个值等于所添加总数量本身[^1]。具体表现为: - 对于任何小于或等于最大分组大小的情况都适用; - 当输入刚好匹配分组界限时不作特殊处理而是正常加入完整的一轮填充。 ```java // Java 中使用 PKCS7Padding 进行填充的例子 Cipher cipher = Cipher.getInstance("SM4/CBC/PKCSPadding"); // 注意这里应更正为标准名称如"PCKS7" SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "SM4"); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); byte[] encryptedData = cipher.doFinal(plainText.getBytes()); ``` 需要注意的是,在实际编程实践中,“PCKS7”可能是笔误或者是某些库特有的命名约定,应当查阅文档确认支持的具体字符串表示形式。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值