由于SM2等加密分组方式,每次要求为16byte的时候,需要进行填充,填充的方式有如下:
pkcs5/pkcs7/ISO10126填充/ANSIX923填充/Zeros填充
解释:
pkcs5 是pkcs7的子集,专门用于填充8字节的或者8的倍数,pkcs7可以填充字节为多个字节
pkcs7的定义:
比如字节长度为10:
例子1、如果当前的数据为8,那么需要填充2个字节,填充字节为0x02,0x02,
例子2、如果当前数据为3,那么需要填充7个字节,填充的字节为0x07,0x07,0x07,0x07,0x07,0x07,0x07
例子3、如果当前数据为10,那么再填充10个字节,填充字节为
0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A
解析的时候,就是判断后续是否有连续一样的值,并且值和长度相等。
pkcs5定义:只是限制了长度,如果为8或者16,和pkcs7一样。
ISO10126的定义:
最后一位标识补位位数n,之前补位n-1个随机值
比如说字节长度为10:
例子1:当前长度为7,那么需要填充3个字节,最后一个字节为0x03,前面两个是随机数,如下填充:0x01,0xff, 0x03
ANSIX923填充:
填充最后一个字节为长度,其余的为0
比如说字节长度为10:
例子1:当前数据为4,需要填充6个字节,那么最后一个字节为0x06,其余5个字节为0,填充如下:
0x00,0x00,0x00,0x00,0x00,0x06
zeros填充的定义:
不够用0填充
比如说字节长度为10:
例子1:当前长度为6,那么需要填充4个字节,填充字节为0x00:
0x00,0x00,0x00,0x00
具体实现方式如下:
定义一个填充结构
//add hmy 2023年7月17日14:18:33
//填充类型
#define NONE_PADDING 0 //不填充
#define PKCS5_PADDING 1 //pkcs5 填充
#define PKCS7_PADDING 2 //pkcs7 填充
#define ISO10126_PADDING 3 //ISO10126填充
#define ANSIX923_PADDING 4 //ANSIX923填充
#define ZERO_PADDING 5 //Zeros填充
#define SEC_TRUE 1000 //成功
#define SEC_FALSE 0 //失败
//填充结构
typedef struct str_padding_info{
U32 PaddingType;//填充类型
U32 dataLen;//数据长度
U32 PaddingBit;//填充对齐字节默认16
U8 dataBuf[255];//缓存消息,255
U32 bufLen;//缓存消息长度,长度为0~255
}PADDING_INFO, * P_PADDING_INFO;
首先初始化结构:
panding_type 填充类型
panding_bit 填充位数 默认为16
padding_info 填充结构
int pandingInit(u32 panding_type, u32 panding_bit, P_PADDING_INFO padding_info)
具体如下:
//add hmy 2023年7月17日14:18:33
//填充结构初始化
//panding_type 填充类型
//panding_bit 填充位数 默认为16
//padding_info 填充结构
int pandingInit(u32 panding_type, u32 panding_bit, P_PADDING_INFO padding_info){
if (padding_info != NULL){
if (panding_type != NONE_PADDING && panding_type != PKCS5_PADDING && panding_type != PKCS7_PADDING && panding_type != ISO10126_PADDING && panding_type != ANSIX923_PADDING &&
panding_type != ZERO_PADDING ){
PRINTF("error:pading_type error\n");
return -1;
}
memset(padding_info->dataBuf, 0 ,sizeof(padding_info->dataBuf));
padding_info->bufLen = 0;
padding_info->dataLen = 0;
padding_info->PaddingBit = panding_bit;
padding_info->PaddingType = panding_type;
}
return 0;
}
填充实现:
//add hmy 2023年7月17日14:19:28
//zero填充去除
SEC_BOOL chip_padding_zero_decode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
int pading_len = 0;
for (int i = *padingLen - 1; i >= *padingLen - padding_info->PaddingBit; i--){
if (paddingbuf[i] == 0){
pading_len++;
}else {
break;
}
}
*padingLen = *padingLen - pading_len;
memset(paddingbuf + *padingLen, 0, pading_len);
return SEC_TRUE;
}
//zero填充
SEC_BOOL chip_padding_zero_encode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
U8 pading_len = (U8)padding_info->PaddingBit - (padding_info->dataLen % (U8)padding_info->PaddingBit);
for (int i =0 ; i < pading_len; i++){
paddingbuf[i] = 0;//产生一个随机数;
}
*padingLen = pading_len;
}
//ansix923填充去除
SEC_BOOL chip_padding_ansix923_decode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
U8 pading_len = paddingbuf[*padingLen - 1];
U8 pos = 0;
if (padding_info->PaddingBit < pading_len){
return SEC_FALSE;
}
for (int i = *padingLen- 2; i >= *padingLen - pading_len ; i--){
if (paddingbuf[i] == 0){
pos++;
}else {
break;
}
}
PRINTF("ansix923 decode pos:%d, pading_len:%d\n",pos, padingLen);
if (pos != pading_len - 1){
return SEC_FALSE;
}
*padingLen = *padingLen - pading_len;
memset(paddingbuf + *padingLen, 0, pading_len);
return SEC_TRUE;
}
//ansix923填充
SEC_BOOL chip_padding_ansix923_encode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
U8 pading_len = (U8)padding_info->PaddingBit - (padding_info->dataLen % (U8)padding_info->PaddingBit);
for (int i =0 ; i < pading_len - 1; i++){
paddingbuf[i] = 0;//产生一个随机数;
}
paddingbuf[pading_len- 1] = pading_len;
*padingLen = pading_len;
return SEC_TRUE;
}
//iso10126 填充去除
SEC_BOOL chip_padding_iso10126_decode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
U8 pading_len = paddingbuf[*padingLen - 1];
U8 pos = 0;
if (padding_info->PaddingBit < pading_len){
return SEC_FALSE;
}
*padingLen = *padingLen - pading_len;
memset(paddingbuf + *padingLen, 0, pading_len);
return SEC_TRUE;
}
//iso10126 填充
SEC_BOOL chip_padding_iso10126_encode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
U8 pading_len = (U8)padding_info->PaddingBit - (padding_info->dataLen % (U8)padding_info->PaddingBit);
srand(time(nullptr));//设置随机数种子
for (int i =0 ; i < pading_len - 1; i++){
paddingbuf[i] = (U8)rand();//产生一个随机数;
}
paddingbuf[pading_len- 1] = pading_len;
*padingLen = pading_len;
return SEC_TRUE;
}
//PKCS#5填充去除
SEC_BOOL chip_padding_pkcs5_decode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
U8 pading_len = paddingbuf[*padingLen - 1];
U8 pos = 0;
if (8 < pading_len){
return SEC_FALSE;
}
for (int i = *padingLen - 1; i >= *padingLen - pading_len; i--){
if (paddingbuf[i] == pading_len){
pos++;
}else {
break;
}
}
if (pos != pading_len){
return SEC_FALSE;
}
*padingLen = *padingLen - pading_len;
memset(paddingbuf + *padingLen, 0, pading_len);
return SEC_TRUE;
}
//pkcs#5填充
SEC_BOOL chip_padding_pkcs5_encode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
U8 pading_len = (U8)8 - (padding_info->dataLen % 8);
for (int i =0 ; i < pading_len; i++){
paddingbuf[i] = pading_len;
}
*padingLen = pading_len;
return SEC_TRUE;
}
//PKCS#7填充去除
SEC_BOOL chip_padding_pkcs7_decode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
U8 pading_len = paddingbuf[*padingLen - 1];
U8 pos = 0;
if (padding_info->PaddingBit < pading_len){
PRINTF("padding_pkcs7_decode bit:%d pading_len:%d\n",padding_info->PaddingBit, pading_len);
return SEC_FALSE;
}
for (int i = *padingLen - 1; i >= *padingLen - pading_len; i--){
if (paddingbuf[i] == pading_len){
pos++;
}else {
break;
}
}
//PRINTF("pkcs7 pos:%d pading_len:%d\n",pos, pading_len);
if (pos != pading_len){
PRINTF("error: pkcs7 pos:%d pading_len:%d\n",pos, pading_len);
return SEC_FALSE;
}
*padingLen = *padingLen - pading_len;
memset(paddingbuf + *padingLen, 0, pading_len);
return SEC_TRUE;
}
//PKCS#7填充
SEC_BOOL chip_padding_pkcs7_encode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
U8 pading_len = (U8)padding_info->PaddingBit - (padding_info->dataLen % (U8)padding_info->PaddingBit);
for (int i =0 ; i < pading_len; i++){
paddingbuf[i] = pading_len;
}
*padingLen = pading_len;
return SEC_TRUE;
}
/**
* 填充处理
* [in] padding_info 填充结构
* [out] paddingbuf 输出填充数据
* [out] padingLen 输出填充长度
*/
SEC_BOOL chip_padding_encode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
switch(padding_info->PaddingType){
case NONE_PADDING:
return SEC_FALSE;
break;
case PKCS5_PADDING:
return chip_padding_pkcs5_encode(padding_info, paddingbuf, padingLen);
break;
case PKCS7_PADDING:
PRINTF("pkcs7 padding\n");
return chip_padding_pkcs7_encode(padding_info, paddingbuf, padingLen);
break;
case ISO10126_PADDING:
return chip_padding_iso10126_encode(padding_info, paddingbuf, padingLen);
break;
case ANSIX923_PADDING:
return chip_padding_ansix923_encode(padding_info, paddingbuf, padingLen);
break;
case ZERO_PADDING:
return chip_padding_zero_encode(padding_info, paddingbuf, padingLen);
break;
}
return SEC_FALSE;
}
/**
* 填充去除处理
* [in] padding_info 填充结构
* [out] paddingbuf 输出填充数据
* [out] padingLen 输出填充长度
*/
SEC_BOOL chip_padding_decode(P_PADDING_INFO padding_info, U8 *paddingbuf, U32 *padingLen){
switch(padding_info->PaddingType){
case NONE_PADDING:
return SEC_FALSE;
break;
case PKCS5_PADDING:
return chip_padding_pkcs5_decode(padding_info, paddingbuf, padingLen);
break;
case PKCS7_PADDING:
return chip_padding_pkcs7_decode(padding_info, paddingbuf, padingLen);
break;
case ISO10126_PADDING:
return chip_padding_iso10126_decode(padding_info, paddingbuf, padingLen);
break;
case ANSIX923_PADDING:
return chip_padding_ansix923_decode(padding_info, paddingbuf, padingLen);
break;
case ZERO_PADDING:
return chip_padding_zero_decode(padding_info, paddingbuf, padingLen);
break;
default:
PRINTF("pading encode type error\n");
return SEC_FALSE;
}
return SEC_FALSE;
}
调用方式,这里给示例调用一次的方式
//一次填充
int main(){
char data[8] = {'1','2','3','4','5','6','7','8'};
int dataLen = 8;
char padding_msg = NULL;
int padding_len = 0;
PADDING_INFO padding_info = {0};
if (pandingInit(PKCS7_PADDING , 16, &padding_info) < 0){
printf("pandingInit error\n");
return -1;
}
padding_info->dataLen = dataLen;
padding_len = padding_info->dataLen + padding_info->PaddingBit;
padding_msg = (char *)malloc(msg_len * sizeof(char));
if (padding_msg == NULL){
printf("error: malloc error\n");
return -1;
}
//填充
if (SEC_TRUE != chip_padding_encode(&padding_info, padding_msg + padding_info->dataLen, &msg_len)){
printf("error: padding error\n");
free(pmsg_in);
return -1;
}
memcpy(padding_msg, data, dataLen);
msg_len = msg_len + dataLen;
printf("fill data:\n");
for (int i = 0; i < msg_len; i++){
printf("%02X ",padding_msg[i]);
}
printf("\n");
if (pandingInit(PKCS7_PADDING , 16, &padding_info) < 0){
printf("pandingInit error\n");
free(pmsg_in);
return -1;
}
padding_info->dataLen = msg_len;
padding_info->bufLen = 0;
if (SEC_TRUE != chip_padding_decode(&padding_info, padding_msg, &msg_len)){
printf("decode error\n");
free(pmsg_in);
return -1;
}
printf("src data:\n");
for (int i = 0; i < msg_len; i++){
printf("%02X ",padding_msg[i]);
}
printf("\n");
free(pmsg_in);
return 0;
}
数据量大的方式,多次填充的方式,那么就需要借助里面的缓冲区了,每次都得判断是否为填充字节倍数,如果不够那么需要截取后部分存储在dataBuf里面,下一包的时候拼接在前面,在最后结束一包的时候添加上去。
本来多包编解码填充也是可以封装的,但是够用了就没有封装,自己和逻辑业务放一起了,这里简单调用解释下
其实就是借用了结构的缓冲区,每次进来的数据是否为对齐字节的倍数,如果是倍数那么不需要处理,如果不是,那么需要把多余的数据放入到填充里面,下一次进来的时候,把数据拼接到之前的前面再查询
//多次填充
int main(){
char data[24] = {0};
int dataLen = 24;
int offset = 0;
char padding_msg[16] = {0};
int padding_len = 0;
for (int i = 0;i < 24; i++){
data[i] = (char)('0'+(i % 9));
}
PADDING_INFO padding_info = {0};
if (pandingInit(PKCS7_PADDING , 16, &padding_info) < 0){
printf("pandingInit error\n");
return -1;
}
//例如:第一次填充 2个字节
dataLen = 2;
if (dataLen < padding_info->PaddingBit){
padding_info->bufLen = dataLen;
memcpy(padding_info->dataBuf,data + offset,dataLen);
padding_info->bufLen = dataLen;
}
offset+= dataLen;
//例如:第二次再填充3个字节
dataLen = 3;
if (dataLen + padding_info->bufLen < padding_info->PaddingBit){
padding_info->bufLen = dataLen;
memcpy(padding_info->dataBuf + padding_info->bufLen,data + offset,dataLen);
padding_info->bufLen += dataLen;
}
offset+= dataLen;
//例如:第三次填充14个字节,这个时候总数为17个字节了,大于对齐字节了,我这里不做通用性判断了,到时候自己实现的额时候
dataLen = 14;
if (dataLen + padding_info->bufLen >= padding_info->PaddingBit && padding_info->bufLen > 0){
//先把填充结构缓存部分拿出来
memcpy(padding_msg, padding_info->dataBuf, padding_info->bufLen);
padding_len = padding_info->bufLen;
padding_info->bufLen = 0;
//再添加数据部分凑成对齐字节的16字节
memcpy(padding_msg + padding_len, data + offset, padding_info->PaddingBit - padding_len);
//把需要添加的剩余字节继续放入到字段里面
memcpy(padding_info->dataBuf,data + offset + (padding_info->PaddingBit - padding_len),dataLen - (padding_info->PaddingBit- padding_len));
padding_info->bufLen =dataLen - (padding_info->PaddingBit- padding_len);
padding_len += padding_info->PaddingBit - padding_len;
//这个时候已经满了对齐字节,可以padding_msg 可以用来处理编码啥的
}
offset += dataLen;
//例如最后一包:填充剩余6个字节
dataLen = 6;
if (dataLen + padding_info->bufLen < padding_info->PaddingBit){
padding_info->bufLen = dataLen;
memcpy(padding_info->dataBuf + padding_info->bufLen,data + offset,dataLen);
padding_info->bufLen += dataLen;
}
offset += dataLen;
//最后一包
dataLen = 6;
if (padding_info->bufLen > 0){
//先把填充结构缓存部分拿出来
memcpy(padding_msg, padding_info->dataBuf, padding_info->bufLen);
padding_len = padding_info->bufLen;
padding_info->bufLen = 0;
memcpy(padding_msg + padding_len, data + oofset, dataLen);
padding_len+= dataLen;
}
padding_info->dataLen = padding_len;
padding_len = 16;
//填充
if (SEC_TRUE != chip_padding_encode(&padding_info, padding_msg + padding_info->dataLen, &padding_len)){
printf("error: padding error\n");
free(pmsg_in);
return -1;
}
padding_len += padding_info->dataLen;
printf("fill data:\n");
for (int i = 0; i < padding_len; i++){
printf("%02X ",padding_msg[i]);
}
printf("\n");
if (pandingInit(PKCS7_PADDING , 16, &padding_info) < 0){
printf("pandingInit error\n");
free(pmsg_in);
return -1;
}
return 0;
}