1.SM4算法介绍
SM4 算法是一种分组密码算法。其分组长度为 16字节,密钥长度也为 16字节。
加密算法与密钥扩展算法均采用 32 轮非线性迭代结构,以字(32 位)为单位进
行加密运算,每一次迭代运算均为一轮变换函数 F。SM4 算法加/解密算法的结构
相同,只是使用轮密钥相反,其中解密轮密钥是加密轮密钥的逆序。
2.代码例子
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
int main(int argc, char *argv[])
{
unsigned char sm4_en[512],sm4_de[512];
int sm4enStrLen,sm4deStrLen;
unsigned char source[20]={0x41,0x12,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10, 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20};
unsigned char keyStr[16]={0x15,0x67,0x28,0xe1,0x5f,0x9a,0xfc,0x01,0xd4,0xb6,0x1b,0x4e,0x44,0x5d,0xbb,0x26};
sm4enStrLen=my_sm4encrpt(keyStr,source,20,sm4_en);
printf("sm4enStrLen:%d",sm4enStrLen);
for(int i=0;i<sm4enStrLen;++i)
{
printf("0x%x",sm4_en[i]);
}
printf("\n");
sm4deStrLen=dencryptStr(keyStr,sm4_en,sm4enStrLen,sm4_de);
printf("sm4deStrLen:%d",sm4deStrLen);
for(int i=0;i<sm4deStrLen;++i)
{
printf("0x%x",sm4_de[i]);
}
printf("\n");
}
int my_sm4encrpt(unsigned char * keyStr,unsigned char * surbuf,int surlen,unsigned char * enbuf)
{
unsigned char *out_buf = enbuf;
int out_len;
int out_padding_len;
int i;
unsigned char *iv;
EVP_CIPHER_CTX *ctx;
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit(ctx, EVP_sm4_ecb(), keyStr, iv);
if( 0 == surlen % 16 )
{
EVP_CIPHER_CTX_set_padding( ctx, 0 );
}
out_len = 0;
EVP_EncryptUpdate(ctx, out_buf, &out_len, surbuf, surlen);
out_padding_len = 0;
EVP_EncryptFinal(ctx, out_buf + out_len, &out_padding_len);
EVP_CIPHER_CTX_free(ctx);
return out_len + out_padding_len;
}
int dencryptStr(unsigned char * sm4PriKey, unsigned char *cEnStr, int cEnstrlen, unsigned char *deStr)
{
unsigned char *iv;
EVP_CIPHER_CTX *ctx;
int len;
int temlen;
int deStrLen;
if (!(ctx = EVP_CIPHER_CTX_new())) {
printf("EVP_CIPHER_CTX_new failed");
}
if (1 != EVP_DecryptInit(ctx, EVP_sm4_ecb(), sm4PriKey, iv)) {
printf("EVP_DecryptInit_ex failed");
}
if (1 != EVP_DecryptUpdate(ctx, deStr, &len, cEnStr, cEnstrlen)) {
printf("EVP_DecryptUpdate failed");
}
if( 0 == len % 16 )
{
EVP_CIPHER_CTX_set_padding( ctx, 0 );
len += 16;
}
if( !EVP_DecryptFinal( ctx, deStr + len, &temlen ) )
{
printf("EVP_DecryptFinal failed");
return EXIT_FAILURE;
}
deStrLen=len+temlen;
printf("解密数据:%d\n",deStrLen);
for (int i = 0;i < deStrLen;i++) {
printf("0x%02x ",*(deStr + i));
}
printf("\n");
EVP_CIPHER_CTX_free(ctx);
return deStrLen;
}