修改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库来解密,流程为:
- 接收Base64编码的加密字符串,解码后提取前缀"Salted__"、盐(第8-16字节)和密文(第16字节起)
- 通过密码短语和盐派生128字节密钥与16字节IV
- 用修改后的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
相关产品推荐
相关产品推荐

