基于RFC3394标准的AES-128-ECB模式的密钥封装(Key Wrap)和解封(Key Unwrap)

  1. 密钥封装(Key Wrap):

    • RFC3394默认IV为0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
    • 使用AES_Encrypt函数对IV和密钥数据块进行加密,并将结果与步数异或。
    • 经过6n轮迭代后,将最终的IV和加密后的数据块复制到输出的密文中。
  2. 密钥解封(Key Unwrap):

    • 从输入的密文中提取了IV和加密的数据块。
    • 逆向执行了6n轮迭代,使用AES_Decrypt函数进行解密,并将结果与步数异或。
    • 最后将解密后的数据块复制到输出的明文中。
  3. 注意事项:

    • AES_EncryptAES_Decrypt函数中关闭了自动填充功能,因为RFC3394算法不使用填充。
    • 使用了EVP_CIPHER_CTX_newEVP_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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值