我用CryptDeriveKey来做加密,现在需要换成openssl来实现原来的代码;
原来的代码大致如下:
HCRYPTPROV g_hProvider = 0;
CryptAcquireContext(&g_hProvider, NULL, MS_STRONG_PROV, PROV_RSA_FULL, 0);
HCRYPTHASH hHash;
HCRYPTKEY hKey;
CryptCreateHash(g_hProvider, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, (LPBYTE)“dbkey”, 5, 0);
CryptDeriveKey(g_hProvider, CALG_3DES_112, hHash, CRYPT_EXPORTABLE, &hKey);
按我的设想:
应该是用字符串“dbkey”做了md5得到的hash key:0a 9c 54 a0 d9 75 8e b2 22 e7 3f 5c c5 b3 5f 36
然后用md5的字符串做加密的session key,但事实并非如此,我发现真正的session key 是:0b 9d 54 a1 d9 75 8f b3 23 e6 3e 5d c4 b3 5e 37
用这个key可以使用openssl加密出原来的结果,但原始的md5串不行;0a 9c 54 a0 d9 75 8e b2 22 e7 3f 5c c5 b3 5f 36 (hash key)
0b 9d 54 a1 d9 75 8f b3 23 e6 3e 5d c4 b3 5e 37 (session key)
对比md5的值发现,部分byte的最后一位有进行修改;但不知道session key和这个hash value到底是什么关系;
我想知道知道hash key,怎么计算出session key
原来的代码大致如下:
HCRYPTPROV g_hProvider = 0;
CryptAcquireContext(&g_hProvider, NULL, MS_STRONG_PROV, PROV_RSA_FULL, 0);
HCRYPTHASH hHash;
HCRYPTKEY hKey;
CryptCreateHash(g_hProvider, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, (LPBYTE)“dbkey”, 5, 0);
CryptDeriveKey(g_hProvider, CALG_3DES_112, hHash, CRYPT_EXPORTABLE, &hKey);
按我的设想:
应该是用字符串“dbkey”做了md5得到的hash key:0a 9c 54 a0 d9 75 8e b2 22 e7 3f 5c c5 b3 5f 36
然后用md5的字符串做加密的session key,但事实并非如此,我发现真正的session key 是:0b 9d 54 a1 d9 75 8f b3 23 e6 3e 5d c4 b3 5e 37
用这个key可以使用openssl加密出原来的结果,但原始的md5串不行;0a 9c 54 a0 d9 75 8e b2 22 e7 3f 5c c5 b3 5f 36 (hash key)
0b 9d 54 a1 d9 75 8f b3 23 e6 3e 5d c4 b3 5e 37 (session key)
对比md5的值发现,部分byte的最后一位有进行修改;但不知道session key和这个hash value到底是什么关系;
我想知道知道hash key,怎么计算出session key
Let n be the required derived key length in bytes. The derived key is the first n bytes of the hash value after the hash computation has been completed by CryptDeriveKey. 我的hash key长度是16byte,比我最终需要的key len都要大,所以,按道理是取前面n位,但是取到的值确实不一样的;上面的session key 是我export出来以后得到的,用这个key可以自己做出跟原来一样的密文
windows的CryptDeriveKey函数在hash结果出来以后,根据des的特性,对每个byte的校验位(最后一位)进行了修改;
从而导致了以下的变化:
0a 9c 54 a0 d9 75 8e b2 22 e7 3f 5c c5 b3 5f 36 (hash key)
|
0b 9d 54 a1 d9 75 8f b3 23 e6 3e 5d c4 b3 5e 37 (session key) 我用openssl对改算法进行还原未能成功,最根本的原因是使用了函数des_set_key_checked
当我反汇编跟踪到修改的内容以后,意识到这个问题,改成des_set_key_unchecked,就没问题了正式:解决问题也许只需要敲1个字母,但明白问题在哪里往往要花上无数倍的功夫
CryptCreateHash(g_hProvider, CALG_SHA1, 0, 0, &hHash);
CryptHashData(hHash, (LPBYTE)“11111”, 5, 0);
CryptDeriveKey(g_hProvider, CALG_AES_128, hHash, CRYPT_EXPORTABLE, &hKey);dwMode = CRYPT_MODE_ECB;
if(!CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0))unsigned long len=16;
CryptDecrypt(hKey, 0, 0, 0, AES_input, &len);然后openssl对应的函数:
unsigned char AES_seed_buffer[20], AES_input[16], AES_temp_result[16];Sha1Encypt("11111", 5, AES_seed_buffer);
AES_set_decrypt_key(AES_seed_buffer, 128, &aes_key);
AES_decrypt(AES_input, AES_temp_result, &aes_key);
其中Sha1Encypt的定义为:
void Sha1Encypt(UCHAR* sBuf, int nLen, UCHAR* sHash)
{
SHA_CTX shaCtx;
SHA1_Init(&shaCtx);
SHA1_Update(&shaCtx, sBuf, nLen);
SHA1_Final(sHash, &shaCtx);
}按理说,CryptoAPI的实现和openssl的实现是等价的,但是其结果就是不相等!高度怀疑其中CryptDeriveKey()并不是简单的对输入进行sha1,是不是还有什么变化? 此外,我直接用SHA1_Final的结果作为AES_set_decrypt_key()的输入,可能和CryptDeriveKey()的实现不一样?另外如何获取CryptoAPI的hKey对应的实际session key呢??多谢各位~~