基于openssl的sm4对称加密算法

  • Post author:
  • Post category:其他




基于openssl库的sm4对称加密算法

问题:解密后多出的填充字符暂未想到怎么去除。


sm4C语言实现源码

gcc sm4.c mm.c -lssl -lcrypto



运算结果:

在这里插入图片描述



sm4算法文件

//sm4.c
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <stdio.h>
#include <stdlib.h>

#include "sm4.h"

static void sm4_show_openssl_error(int8_t* title)
{
	int8_t buf[1024];

	ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
	printf("%s: %s\n", title, buf);
}


static const EVP_CIPHER *sm4_get_mode(int8_t *mode)
{
	switch (*mode) {
	case '0':
		return EVP_sm4_ecb();
	case '1':
		return EVP_sm4_cbc();
	case '2':
		return EVP_sm4_cfb128();
	default:
		return NULL;
	}
}

static int32_t sm4_get_rand(uint8_t *out, uint32_t len)
{   
    BIGNUM *rnd;
    uint8_t buf[32];
    uint32_t idx;
    
    rnd = BN_new();
    if (NULL == rnd) {
        return -1;
    }
    
    if (!BN_rand(rnd, 256, 1, 1)) {
        return -1;
    }
    
    if (BN_bn2binpad(rnd, buf, 32) != 32) {
        return -1;
    }
    BN_free(rnd);
    show_hex("rand", buf, 32);
    
    for (idx = 0; idx < len; idx++) {
        idx = idx >= 32 ? 0 : idx;
        *out++ = buf[idx];
    }
    
    return 0;
}

int32_t sm4_gen_key(sm4_data_t *data, uint8_t *key, uint32_t length)
{
    if (sm4_get_rand(key, length)) {
        return -1;
    }
	data->key = key;

	return 0;
}

int32_t sm4_gen_iv(sm4_data_t *data, uint8_t *iv, uint32_t length)
{
    if (sm4_get_rand(iv, length)) {
        return -1;
    }
	data->iv = iv;

	return 0;
}

int32_t sm4_encrypt_data(sm4_data_t *data, void *in, uint32_t ilen, void *out, uint32_t *olen)
{
	EVP_CIPHER_CTX *ctx = data->ctx;
	const EVP_CIPHER *mode = sm4_get_mode(data->mode);
	int32_t len = 0, pad = 0;

	EVP_EncryptInit_ex(ctx, mode, NULL, data->key, data->iv);

	if (ilen % SM4_BLOCK_SIZE != 0) {
		pad = 1;
	}
	EVP_CIPHER_CTX_set_padding(ctx, pad);

	if (!EVP_EncryptUpdate(ctx, out, &len, in, ilen)) {
		return -1;
	}
	*olen = len;
	len = 0;

	if (!EVP_EncryptFinal_ex(ctx, out + *olen, &len)) {
		return -1;
	}

	*olen += len;

	return 0;
}

int32_t sm4_decrypt_data(sm4_data_t *data, void *in, uint32_t ilen, void *out, uint32_t *olen)
{
	EVP_CIPHER_CTX *ctx = data->ctx;
	const EVP_CIPHER *mode = sm4_get_mode(data->mode);
	int32_t len = 0;

	EVP_DecryptInit_ex(ctx, mode, NULL, data->key, data->iv);
	EVP_CIPHER_CTX_set_padding(ctx, 0);

	if (!EVP_DecryptUpdate(ctx, out, &len, in, ilen)) {
		return -1;
	}
	*olen = len;
	len = 0;

	if (EVP_DecryptFinal_ex(ctx, out + *olen, &len)) {
		return -1;
	}
	*olen += len;

	return 0;
}

int32_t sm4_data_init(sm4_data_t *data, void *mode)
{
	EVP_CIPHER_CTX *ctx;

	ctx = EVP_CIPHER_CTX_new();
	if (NULL == ctx) {
		return -1;
	}	

	data->mode = mode;
	data->ctx = ctx;

	return 0;
}

int32_t sm4_data_exit(sm4_data_t *data)
{
	EVP_CIPHER_CTX_free(data->ctx);

	return 0;
}



头文件

//sm4.h
#ifndef _SM4_H_
#define _SM4_H_

#include <stdint.h>

#define SM4_BLOCK_SIZE       (16)

typedef struct
{
	void *ctx;
	void *key;
	void *iv;
	void *mode;
}sm4_data_t;

#define SM4_MODE_ECB	"0_ecb"
#define SM4_MODE_CBC	"1_cbc"
#define SM4_MODE_CFB	"2_cfb"

int32_t sm4_gen_key(sm4_data_t *data, uint8_t *key, uint32_t length);
int32_t sm4_gen_iv(sm4_data_t *data, uint8_t *iv, uint32_t length);

int32_t sm4_encrypt_data(sm4_data_t *data, void *in, uint32_t ilen, void *out, uint32_t *olen);
int32_t sm4_decrypt_data(sm4_data_t *data, void *in, uint32_t ilen, void *out, uint32_t *olen);

int32_t sm4_data_init(sm4_data_t *data, void *mode);
int32_t sm4_data_exit(sm4_data_t *data);

#endif



main函数

//mm.c
#include <stdio.h>
#include "sm4.h"

static uint8_t txt[] = {
	0xf5, 0xa0, 0x3b, 0x06, 0x48, 0xd2, 0xc4 ,0x63, 0x0e, 0xea, 0xc5, 0x13, 0xe1, 0xbb, 0x81, 0xa1,
	0x59, 0x44, 0xda, 0x38, 0x27, 0xd5, 0xb7, 0x41, 0x43, 0xac, 0x7e, 0xac, 0xee, 0xe7, 0x20, 0xb3,
	0xb1, 0xb6, 0xaa, 0x29, 0xdf, 0x21, 0x2f, 0xd8, 0x76, 0x31, 0x82, 0xbc, 0x0d, 0x42, 0x1c, 0xa1,
	0xbb, 0x90, 0x38, 0xfd, 0x1f, 0x7f, 0x42, 0xd4, 0x84, 0x0b, 0x69, 0xc4, 0x85, 0xbb, 0xc1, 0xaa,
	0x11, 0x22,
};

static int32_t show_hex(int8_t* title, void* buf, uint32_t total)
{
	uint32_t idx;
	uint8_t* data = buf;

	printf("%s(%d):\n\t", title, total);
	for (idx = 0; idx < total; idx++) {
		printf("%02hhx", data[idx]);
		printf("%s", 15 == (idx & 15) ? "\n\t" : ", ");
	}
	printf("\n");
	
	return 0;
}

int32_t main(void)
{
	uint8_t key[16] = {0};
	uint8_t iv[16] = {0};
	uint8_t cipher[128] = {0};
	uint8_t buf[128] = {0};
	uint32_t len;
	sm4_data_t data;

	if (sm4_data_init(&data, SM4_MODE_CBC)) {
		return -1;
	}

	sm4_gen_key(&data, key, sizeof(key));
	sm4_gen_iv(&data, iv, sizeof(iv));
	show_hex("key", key, sizeof(key));
	show_hex("iv", iv, sizeof(iv));

	show_hex("data", txt, sizeof(txt));
	sm4_encrypt_data(&data, txt, sizeof(txt), cipher, &len);

	show_hex("cipher", cipher, len);

	sm4_decrypt_data(&data, cipher, len, buf, &len);
	show_hex("buf", buf, len);

	sm4_data_exit(&data);
	return 0;
}



版权声明:本文为weixin_42282031原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。