0


sm2签名与sm4加密(一)

因为某些不可抗原因,友商加密平台系统无法提供接口进行加密验签,以至于需要自己实现监管要求的加密验签。

接口要求,报文先经过sm2生成签名,之后进行sm4加密。收到报文后,先进行sm4解密,解密后将报文进行验签。验证成功之后既结束全部流程。

所以整体上分为两大部分,一为sm4加密,二为sm2签名。

首先先说简单的sm4加密,调用代码参考了开源项目openssl。

1.准备密钥和需要加密的报文

2.将报文进行分组,每16个字也就是128bit为一组,这里采用最简单的ECB分组方式,对不足16位的最后一组进行补位,采用pkcs7方式进行补位,就是差几位就补几位的几,比如8位差八位,就补八个八,对于16整数倍补16位的16(方便解码)

3.生成轮密钥,将32位的密钥分成八位一组的四组,编号为k0k1k2k3,通过互相运算及s盒,得到k4,再选取k1k2k3k4,运算得到k5,。循环32次,得到k0-k35,选取k4-k35为生成的轮密钥结果

4.进行加密,同样将一组16个字也是32位分成八位一组的四组,轮加密Bi⊕F(B(i-1)⊕B(i-2)⊕B(i-3)⊕k(i-4))得到下一组,最终得到B31-B35,拼成一个串返回这一组的加密结果,单组加密完毕。

最终把所有组拼在一起就是加密结果。

解密正好相反,因为必然是16的整数倍,所以直接分组。将生成的轮密钥与加密后的报文进行逆运算,最终得到补码后的原报文,取报文最后一位,截取最后一位对应的数字得到原始信息

参考代码:


#include "e_os2.h"
#include "sm4.h"

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

void sm4_decrypt_ecb(unsigned char* key,
    int length,
    unsigned char* input,
    unsigned char* output)
{
    unsigned char* tmp=NULL ;
    unsigned char* tmp1 = NULL;
    int length1 = length;

    int bodylength;                /*解密后报文体长度 */
    int pkcs = 0;                      /*补位值 */
    SM4_KEY ks;                   /*轮密钥结构体 */

    tmp = (unsigned char*)malloc(sizeof(char) * length+1);
    memset(tmp, 0x00, length + 1);
    tmp1 = tmp;
    ossl_sm4_set_key(key, &ks);  /*通过密钥生成32轮密钥*/

    while (length1 > 0)
    {
        ossl_sm4_decrypt(input, tmp, &ks); /* 进行单组解密,暂存至tmp*/
        input += 16;
        tmp += 16;
        length1 -= 16;
    }

    bodylength = strlen(tmp1);
    pkcs = (int)tmp1[bodylength - 1];   /*取最后一位pkcs补位字符,转换成数字*/

    strncpy(output, tmp1, (bodylength - pkcs));  /*去除补位字符,拷贝至输出*/

    tmp = NULL;
    tmp1 = NULL;
}
void sm4_encrypt_ecb(unsigned char* key,
    int length,
    unsigned char* input,
    unsigned char* output) {
    int bodylength;                /*补位后报文体长度 */
    SM4_KEY ks;                   /*轮密钥结构体 */
    unsigned char pkcs;                      /*补位值 */
    unsigned char* tmp= output;

    pkcs = 16 - (length % 16);                /*获取补位值*/
    memset(input + strlen(input), pkcs, pkcs); /*报文补位*/

    ossl_sm4_set_key(key, &ks);  /*通过密钥生成32轮密钥*/
    bodylength = strlen(input);
    while (bodylength > 0)
    {
        ossl_sm4_encrypt(input, tmp, &ks); /* 进行单组加密*/
        input += 16;
        tmp += 16;
        bodylength -= 16;
    }
}
void main() {
    char key[16+1] ;
    char input[100];
    char input1[100];
    char output1[100];
    char output[100];

    memset(key,0x00, sizeof(key));
    memset(input, 0x00, sizeof(input));
    memset(input1, 0x00, sizeof(input1));
    memset(output1, 0x00, sizeof(output1));
    memset(output, 0x00, sizeof(output));
    
    strcpy(key, "1234567890abcdef");
    strcpy(input, "1234567890abcdeghhjuuu5555678900uuuuuuu");
    sm4_encrypt_ecb(key, strlen(input), input, output);
    strcpy(input1, output);
    sm4_decrypt_ecb(key, strlen(input1), input1, output1);
    printf("input=[%s],\noutput=[%s]", input, output1);
}
标签: c语言 安全 算法

本文转载自: https://blog.csdn.net/2301_76249656/article/details/129668922
版权归原作者 glodrar 所有, 如有侵权,请联系我们删除。

“sm2签名与sm4加密(一)”的评论:

还没有评论