You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修改tiny-AES-c库解密CryptoJS生成的128字节密钥AES-CBC数据

非标准128字节AES密钥的解密问题

背景

我有部分数据是通过CryptoJS的CryptoJS.AES.encrypt(message, 'passphrase123')加密的。CryptoJS会用传入的密码短语派生AES密钥和IV,其中CryptoJS.algo.AES.keySize指定密钥长度(以4字节的“字”为单位):比如CryptoJS.algo.AES.keySize = 8对应32字节的AES256密钥。

但我的数据是用CryptoJS.algo.AES.keySize = 32加密的,这会生成128字节的非标准AES密钥(正常AES仅支持16/24/32字节密钥长度),但CryptoJS并未报错并完成了加密。

尝试的解决方案与代码

我尝试编写C程序,通过修改tiny-AES-c库来解密,流程为:

  1. 接收Base64编码的加密字符串,解码后提取前缀"Salted__"、盐(第8-16字节)和密文(第16字节起)
  2. 通过密码短语和盐派生128字节密钥与16字节IV
  3. 用修改后的tiny-AES-c尝试解密

我的C解密代码

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
#include "aes.h" //TinyAES library
#include "derivekey.h" //Derives a 128 byte AES key and 16 byte IV from a repeated MD5 hash of the passphrase and salt provided.

#define CBC 1
#define AES256 1 //I define AES256 for tiny-AES-c, even though it's 1024 bits, not 256 bits

static int decrypt_message(void);


int main(void)
{
    int exit;

    exit = decrypt_message();

    return exit;
}

const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

int b64invs[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58,
    59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5,
    6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
    29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
    43, 44, 45, 46, 47, 48, 49, 50, 51 };
    

size_t b64_get_decoded_size(const char *in)
{
    size_t len;
    size_t ret;
    size_t i;

    if (in == NULL)
        return 0;

    len = strlen(in);
    ret = len / 4 * 3;

    for (i=len; i-->0; ) {
        if (in[i] == '=') {
            ret--;
        } else {
            break;
        }
    }

    return ret;
}


int b64_decode(const char *in, unsigned char *out, size_t outlen)
{
    size_t len;
    size_t i;
    size_t j;
    int    v;

    if (in == NULL || out == NULL)
        return 0;

    len = strlen(in);
    if (outlen < b64_get_decoded_size(in) || len % 4 != 0)
        return 0;

    for (i=0, j=0; i<len; i+=4, j+=3) {
        v = b64invs[in[i]-43];
        v = (v << 6) | b64invs[in[i+1]-43];
        v = in[i+2]=='=' ? v << 6 : (v << 6) | b64invs[in[i+2]-43];
        v = in[i+3]=='=' ? v << 6 : (v << 6) | b64invs[in[i+3]-43];

        out[j] = (v >> 16) & 0xFF;
        if (in[i+2] != '=')
            out[j+1] = (v >> 8) & 0xFF;
        if (in[i+3] != '=')
            out[j+2] = v & 0xFF;
    }

    return 1;
}



static int decrypt_message(void)
{
    char       *out;
    size_t      out_len;
    char *msg = "U2FsdGVkX1Zr2Kg8jTR63TAZvbY15e5R5gmV8PonVOykoOYsnXzehHf0fq97CixhocTP9/7wJ1pQ==";
    
    out_len = b64_get_decoded_size(msg)+1;
    out = malloc(out_len);
    
    if (!b64_decode(msg, (unsigned char *)out, out_len)) {
        printf("Decode Failure\n");
        return 1;
    }

    char *cipherprefix;
    char *ciphersalt;
    char *ciphertext;
    
    cipherprefix = malloc(8); //Should be "Salted__"
    ciphersalt = malloc(8);
    ciphertext = malloc(out_len-16);

    for(int i1=0; i1<8; i1++){  
            cipherprefix[i1] = out[i1];
    }
    for(int i2=8; i2<16; i2++){
            ciphersalt[i2-8] = out[i2];
    }
    for(int i3=16; i3<strlen(out); i3++){
            ciphertext[i3-16] = out[i3];
    }

    uint8_t key;
    uint8_t iv;
    
    char* pwd = "passphrase123";
    derive_aes1024_key(pwd, ciphersalt, key, iv);
    
    struct AES_ctx ctx;
    AES_init_ctx_iv(&ctx, key, iv);
    AES_CBC_decrypt_buffer(&ctx, ciphertext, sizeof(ciphertext));
    
    printf((char*) ciphertext);

}

修改后的tiny-AES-c代码

aes.c中的定义修改

/*****************************************************************************/
/* Defines:                                                                  */
/*****************************************************************************/
// The number of columns comprising a state in AES. This is a constant in AES. Value=4
#define Nb 4

#if defined(AES256) && (AES256 == 1)
    #define Nk 32 //changed from 8 (32 = 128bytes / 4)
    #define Nr 38 //changed from 14 (CryptoJS uses algorthim to determine rounds: rounds = key/32 + 6. So [1024bits / 32] + 6)
#elif defined(AES192) && (AES192 == 1)
    #define Nk 6
    #define Nr 12
#else
    #define Nk 4        // The number of 32 bit words in a key.
    #define Nr 10       // The number of rounds in AES Cipher.
#endif

aes.h中的定义修改

#define AES_BLOCKLEN 16 // Block length in bytes

#if defined(AES256) && (AES256 == 1)
    #define AES_KEYLEN 128 //changed from 32
    #define AES_keyExpSize 624 // Default value is 240, I'm not sure if this is what I'm supposed to change this to
#elif defined(AES192) && (AES192 == 1)
    #define AES_KEYLEN 24
    #define AES_keyExpSize 208
#else
    #define AES_KEYLEN 16   // Key length in bytes
    #define AES_keyExpSize 176
#endif

当前问题

即使修改了tiny-AES-c的密钥长度和轮数定义,使用正确的密钥和IV运行程序仍无法正确解密数据,求解决方向。


内容的提问来源于stack exchange,提问作者singlethread

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:04:55