我用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

解决方案 »

  1.   

    补充一下:msdn上有这样一段:
    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可以自己做出跟原来一样的密文
      

  2.   

    问题搞定了,还是因为我对des的算太不了解,与大家分享一下:des的密钥是8个字节(64bit),但其实每个字节最后的位都是校验位,不参与加密解密,实际参与bit只有56位;
    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个字母,但明白问题在哪里往往要花上无数倍的功夫
      

  3.   

    我也遇到了这种问题,有人用我的工具写脚本,3des密钥0102..........0f10与0102..........0f11一样,也是看过原理之后才发现的。
      

  4.   

    我也有同样的问题!!想把CryptoAPI的函数转化为Openssl的函数.但是折腾了好几天,还是不行! 求救高手,先谢谢啦!!不过我的算法稍有不同: 
    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呢??多谢各位~~