-
密钥封装(Key Wrap):
- RFC3394默认IV为
0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
。 - 使用
AES_Encrypt
函数对IV和密钥数据块进行加密,并将结果与步数异或。 - 经过6n轮迭代后,将最终的IV和加密后的数据块复制到输出的密文中。
- RFC3394默认IV为
-
密钥解封(Key Unwrap):
- 从输入的密文中提取了IV和加密的数据块。
- 逆向执行了6n轮迭代,使用
AES_Decrypt
函数进行解密,并将结果与步数异或。 - 最后将解密后的数据块复制到输出的明文中。
-
注意事项:
- 在
AES_Encrypt
和AES_Decrypt
函数中关闭了自动填充功能,因为RFC3394算法不使用填充。 - 使用了
EVP_CIPHER_CTX_new
和EVP_CIPHER_CTX_free
来管理加密上下文。 - 在加密和解密函数中检查了每个
EVP
函数调用的返回值,以确保操作成功。
- 在
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <string.h>
void AES_Encrypt(uint8_t* plaintext1, uint8_t* plaintext2, uint8_t* key)
{
unsigned char tplaintext[16];
unsigned char tciphertext[32];
memset(tplaintext, 0, sizeof(tplaintext));
memset(tciphertext, 0, sizeof(tciphertext));
memcpy(tplaintext, plaintext1, 8);
memcpy(tplaintext + 8, plaintext2, 8);
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (!ctx)
{
printf("Error creating cipher context!\n");
return;
}
//初始化加密操作
if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
{
printf("Error initializing encryption!\n");
EVP_CIPHER_CTX_free(ctx);
return;
}
//不使用自动填充功能
EVP_CIPHER_CTX_set_padding(ctx, 0);
//执行加密操作
int outlen;
if (1 != EVP_EncryptUpdate(ctx, tciphertext, &outlen, tplaintext, 16))
{
printf("Error encrypting plaintext!\n");
EVP_CIPHER_CTX_free(ctx);
return;
}
//结束加密操作
int templen;
if (1 != EVP_EncryptFinal_ex(ctx, tciphertext + outlen, &templen))
{
printf("Error finalizing encryption!\n");
EVP_CIPHER_CTX_free(ctx);
return;
}
outlen += templen;
printf("Ciphertext is:\n");
for (int i = 0; i < 16; i++)
{
printf("%02x", tciphertext[i]);
if ((i+1) % 8 == 0) printf(" ");
}
printf("\n");
//清理资源
EVP_CIPHER_CTX_free(ctx);
memcpy(plaintext1, tciphertext, 8);
memcpy(plaintext2, tciphertext + 8, 8);
}
void AES_Decrypt(uint8_t* ciphertext1, uint8_t* ciphertext2, uint8_t* key)
{
unsigned char tplaintext[32];
unsigned char tciphertext[16];
memset(tplaintext, 0, sizeof(tplaintext));
memset(tciphertext, 0, sizeof(tciphertext));
memcpy(tciphertext, ciphertext1, 8);
memcpy(tciphertext + 8, ciphertext2, 8);
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (!ctx)
{
printf("Error creating cipher context!\n");
return;
}
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
{
printf("Error initializing decryption!\n");
EVP_CIPHER_CTX_free(ctx);
return;
}
//不使用自动填充功能
EVP_CIPHER_CTX_set_padding(ctx, 0);
int outlen;
if (1 != EVP_DecryptUpdate(ctx, tplaintext, &outlen, tciphertext, 16))
{
printf("Error decrypting ciphertext!\n");
EVP_CIPHER_CTX_free(ctx);
return;
}
int templen;
if (1 != EVP_DecryptFinal_ex(ctx, tciphertext + outlen, &templen))
{
printf("Error finalizing decryption!\n");
EVP_CIPHER_CTX_free(ctx);
return;
}
outlen += templen;
printf("Plaintext is:\n");
for (int i = 0; i < 16; i++)
{
printf("%02x", tciphertext[i]);
if ((i + 1) % 8 == 0) printf(" ");
}
printf("\n");
EVP_CIPHER_CTX_free(ctx);
memcpy(ciphertext1, tplaintext, 8);
memcpy(ciphertext2, tplaintext + 8, 8);
}
//根据RFC3394算法进行密钥封装
void KeyWrap(uint8_t* kek, uint8_t* plaintext, int plaintext_len, uint8_t* ciphertext)
{
uint8_t IV[8] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
uint8_t R[2][8]; //存储密钥数据块
//将明文密钥数据复制到R中
memcpy(R[0], plaintext, plaintext_len);
//执行6n轮迭代
for (int i = 0; i < 6 * (plaintext_len / 8); i++)
{
//将IV与R[0]R[1]轮流进行AES加密,并将结果与i+1异或
AES_Encrypt(IV, R[i % 2], kek); //加密
IV[7] ^= (uint8_t)(i + 1); //与步数异或
}
memcpy(ciphertext, IV, sizeof(IV));
memcpy(ciphertext + sizeof(IV), R[0], sizeof(R));
}
void KeyUnWrap(uint8_t* kek, uint8_t* plaintext, uint8_t* ciphertext, int ciphertext_len)
{
uint8_t R[3][8]; //存储密钥数据块
int plaintext_len = ciphertext_len - 8;
//将密文数据复制到R中
memcpy(R[0], ciphertext, ciphertext_len);
//执行6n轮迭代
for (int i = 6 * (plaintext_len / 8); i > 0; i--)
{
R[0][7] ^= (uint8_t)i; //与步数异或
AES_Decrypt(R[0], R[(i - 1) % 2 + 1], kek); //进行ECB解密
}
memcpy(plaintext, R[1], plaintext_len);
}
int main() {
uint8_t kek[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
uint8_t plaintext[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
uint8_t ciphertext[24];
KeyWrap(kek, plaintext, 16, ciphertext);
printf("Ciphertext: ");
for (int i = 0; i < 24; ++i) {
printf("%02X ", ciphertext[i]);
}
printf("\n");
KeyUnWrap(kek, plaintext, ciphertext, 24);
printf("Plaintext: ");
for (int i = 0; i < 16; ++i) {
printf("%02X ", plaintext[i]);
}
printf("\n");
return 0;
}
标签:ECB,tciphertext,CTX,ctx,uint8,EVP,Key,printf,Wrap
From: https://blog.csdn.net/2201_75357739/article/details/143211060