【C】openssl库中des/3des的EVP接口使用
openssl库中des/3des的EVP接口使用
evp函数介绍
-
EVP_CIPHER_CTX_new
功能:用于创建和初始化加解密上下文 -
EVP_DecryptInit_ex
功能:初始化加解密操作 -
EVP_CIPHER_CTX_set_padding
功能:启用或禁用填充
参数:- 0:禁用填充
- 1:启用填充,默认是PKCS7方式
-
EVP_DecryptUpdate
功能:执行加解密 -
EVP_DecryptFinal_ex
功能:填充额外数据 -
EVP_CIPHER_CTX_free
功能:释放加解密上下文
代码实现
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/provider.h>
/*
* 使用指南:
* 1. 确保已安装OpenSSL 3.6或更高版本,并且包含legacy provider以支持DES算法。
* 2. 编译命令示例:
* gcc des_example.c -o des_example -w -lssl -lcrypto
* 3. 运行程序:
* ./des_example
*/
typedef enum {
DES_CBC, // 单DES CBC模式
DES3_CBC_2KEY, // 双重DES CBC模式
DES3_CBC_3KEY // 三重DES CBC模式
} DesCryptoMode;
typedef enum {
PADDING_NONE, // 无填充
PADDING_PKCS7, // PKCS7填充
PADDING_ZERO // 零填充
} DesPaddingMode;
// 初始化OpenSSL库
int init_openssl()
{
// 加载遗留provider以支持DES 3DES算法
if (OSSL_PROVIDER_load(NULL, "legacy") == NULL) {
fprintf(stderr, "Failed to load legacy provider\n");
return -1;
}
if (OSSL_PROVIDER_load(NULL, "default") == NULL) {
fprintf(stderr, "Failed to load default provider\n");
return -1;
}
return 0;
}
// 打印十六进制数据
void print_hex(const char *label, const unsigned char *data, int len)
{
printf("%s: ", label);
for (int i = 0; i < len; i++) {
printf("%02X", data[i]);
}
printf("\n");
}
EVP_CIPHER *get_cipher(DesCryptoMode mode)
{
switch (mode) {
case DES_CBC:
return EVP_des_cbc();
case DES3_CBC_2KEY:
return EVP_des_ede_cbc();
case DES3_CBC_3KEY:
return EVP_des_ede3_cbc();
default:
return NULL;
}
}
// DES加密函数
int des_encrypt(const unsigned char *plaintext, int plaintext_len,
const unsigned char *key, const unsigned char *iv,
unsigned char *ciphertext, int *ciphertext_len,
DesCryptoMode mode, DesPaddingMode padding)
{
EVP_CIPHER_CTX *ctx = NULL;
int len = 0;
int total_len = 0;
// 检查数据长度是否为8的倍数(DES块大小)
if (plaintext_len % 8 != 0) {
fprintf(stderr, "Data length must be multiple of 8 bytes for no padding\n");
return -1;
}
// 创建并初始化加密上下文
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
fprintf(stderr, "Failed to create cipher context\n");
return -1;
}
EVP_CIPHER *cipher = get_cipher(mode);
// 初始化DES CBC加密操作
if (EVP_EncryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv) != 1) {
fprintf(stderr, "Failed to initialize encryption\n");
EVP_CIPHER_CTX_free(ctx);
return -1;
}
// 禁用填充
EVP_CIPHER_CTX_set_padding(ctx, padding == PADDING_NONE ? 0 : 1);
// 执行加密
if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len) != 1) {
fprintf(stderr, "Failed to encrypt data\n");
EVP_CIPHER_CTX_free(ctx);
return -1;
}
total_len = len;
// 对于无填充模式,Final操作通常不会产生额外数据
if (EVP_EncryptFinal_ex(ctx, ciphertext + len, &len) != 1) {
fprintf(stderr, "Failed to finalize encryption\n");
EVP_CIPHER_CTX_free(ctx);
return -1;
}
total_len += len;
*ciphertext_len = total_len;
EVP_CIPHER_CTX_free(ctx);
return 0;
}
// DES解密函数
int des_decrypt(const unsigned char *ciphertext, int ciphertext_len,
const unsigned char *key, const unsigned char *iv,
unsigned char *plaintext, int *plaintext_len,
DesCryptoMode mode, DesPaddingMode padding)
{
EVP_CIPHER_CTX *ctx;
int len;
int total_len = 0;
// 检查数据长度是否为8的倍数
if (ciphertext_len % 8 != 0) {
fprintf(stderr, "Ciphertext length must be multiple of 8 bytes\n");
return -1;
}
// 创建并初始化解密上下文
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
fprintf(stderr, "Failed to create cipher context\n");
return -1;
}
// 初始化DES CBC解密操作
if (EVP_DecryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv) != 1) {
fprintf(stderr, "Failed to initialize decryption\n");
EVP_CIPHER_CTX_free(ctx);
return -1;
}
// 禁用填充
EVP_CIPHER_CTX_set_padding(ctx, padding == PADDING_NONE ? 0 : 1);
// 执行解密
if (EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len) != 1) {
fprintf(stderr, "Failed to decrypt data\n");
EVP_CIPHER_CTX_free(ctx);
return -1;
}
total_len = len;
// 对于无填充模式 final操作通常不会产生额外数据
if (EVP_DecryptFinal_ex(ctx, plaintext + len, &len) != 1) {
fprintf(stderr, "Failed to finalize decryption\n");
EVP_CIPHER_CTX_free(ctx);
return -1;
}
total_len += len;
*plaintext_len = total_len;
EVP_CIPHER_CTX_free(ctx);
return 0;
}
int main(void)
{
// 初始化OpenSSL
if (init_openssl() != 0) {
fprintf(stderr, "OpenSSL initialization failed\n");
return 1;
}
// 示例数据
// 明文数据长度必须是8的倍数(DES块大小)
unsigned char *plaintext = "12345678";
// 密钥长度必须大于等于8字节 DES使用前8字节
unsigned char *key = "123456781234567812345678";
// 初始向量IV可以为NULL 表示全0初始化向量
// unsigned char *iv = NULL;
unsigned char *iv = "00000000";
DesCryptoMode mode = DES3_CBC_3KEY;
DesPaddingMode padding = PADDING_NONE;
unsigned char ciphertext[8];
unsigned char decrypted[8];
int ciphertext_len, decrypted_len;
int plaintext_len = strlen(plaintext);
printf("=== OpenSSL 3.6 DES CBC 无填充 EVP示例 ===\n");
printf("明 文: %s\n", plaintext);
printf("明文长度: %d\n", plaintext_len);
printf("密 钥: %s\n", plaintext);
printf("初始向量: %s\n", iv == NULL ? "NULL" : iv);
// 加密
printf("\n--- 加密过程 ---\n");
if (des_encrypt(plaintext, plaintext_len, key, iv, ciphertext, &ciphertext_len, mode, padding) == 0) {
printf("加密成功\n");
print_hex("密文", ciphertext, ciphertext_len);
// 解密
printf("\n--- 解密过程 ---\n");
if (des_decrypt(ciphertext, ciphertext_len, key, iv, decrypted, &decrypted_len, mode, padding) == 0) {
printf("解密成功\n");
printf("解密数据: %s\n", decrypted);
// 验证结果
printf("\n--- 验证结果 ---\n");
if (memcmp(plaintext, decrypted, plaintext_len) == 0) {
printf("✓ 加密解密验证成功!\n");
} else {
printf("✗ 加密解密验证失败!\n");
}
} else {
printf("解密失败\n");
}
} else {
printf("加密失败\n");
}
return 0;
}
浙公网安备 33010602011771号