我正在尝试使用 AES128(ECB 模式)加密文本块,以测试我使用的 ECB-AES123 测试向量产生的加密/解密功能,来自“建议块密码操作模式:方法和技术,NIST 特别出版物 800 -38A,2001 年版; “。
例如:
Key: 2b7e151628aed2a6abf7158809cf4f3c (16 bytes)
Input Plaintext: 6bc1bee22e409f96e93d7e117393172a (16 bytes)
Resulted Ciphertext: 3ad77bb40d7a3660a89ecaf32466ef97 (16 bytes)
对于 OpenSSL,以下代码完美运行:
AES_KEY aes_key;
//key vector of bytes 2b7e151628aed2a6abf7158809cf4f3c (16 bytes)
//input_vector also vector of bytes 6bc1bee22e409f96e93d7e117393172a (16 bytes)
if ( AES_set_encrypt_key( &key[0], 128, &aes_key ) != 0 )
{
return false;
}
AES_ecb_encrypt( &input_vector[ 0 ], &encrypted_vector[ 0 ], &aes_key, AES_ENCRYPT );
//encrypted_vector will have expected value 3ad77bb40d7a3660a89ecaf32466ef97 (16 bytes)
但同时我需要使用 Microsoft 的 Crypto API 实现相同的功能。以下是应该这样做的代码:
HCRYPTPROV crypto_provider_handle;
HCRYPTHASH crypto_hash_handle;
HCRYPTKEY crypto_key_handle;
CryptAcquireContext( &crypto_provider_handle, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES,
CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET );
CryptCreateHash( crypto_provider_handle, CALG_SHA1, 0, 0, &crypto_hash_handle );
CryptHashData( crypto_hash_handle, &key[ 0 ], key.size( ), 0 );
CryptDeriveKey( crypto_provider_handle, CALG_AES_128, crypto_hash_handle,
0x00800000 | CRYPT_NO_SALT, crypto_key_handle );
// Set ECB mode
DWORD mode = CRYPT_MODE_ECB;
CryptSetKeyParam( crypto_key_handle, KP_MODE, (BYTE*)&mode, 0 );
// input_data is buffer of 16 bytes with additional space, total size 16*2
// input_size equals 16
CryptEncrypt( crypto_key_handle, NULL, TRUE, 0, input_data, &input_size, 16*2 );
但是这段代码会产生不同的结果。
- 如果“Final”为 TRUE(如上所示),input_data 的大小将是 32 字节,这根本与预期值不匹配。根据 MSDN,没关系,因为在这种情况下,数据会附加一个额外的填充块。
- 如果“Final”为 FALSE,则 input_data 将具有预期的大小(16 字节),但结果也会错误。
我一直坚持这个案子,我不明白我错过了什么。是否可以产生与 OpenSSL 相同的结果(根据规范预期)?为什么 ECB 模式下的 AES128 会改变结果的大小(在 ECB 模式下不应该这样做)?