1

我在 C++ 中有这段代码(AnsiString 是 char* 缓冲区的包装器):

BOOL HashIt(AnsiString &pw,BYTE *buf,BYTE &len)
{
   HCRYPTPROV cp;
   CryptAcquireContext(&cp,NULL,NULL,PROV_RSA_AES,CRYPT_VERIFYCONTEXT);

   HCRYPTHASH ch;
   CryptCreateHash(cp,CALG_MD5,0,0,&ch);

   CryptHashData(ch,(BYTE*)pw.c_str(),pw.Length(),0);

   HCRYPTKEY kc;
   CryptDeriveKey(cp,CALG_3DES,ch,CRYPT_EXPORTABLE,&kc);
   CryptExportKey(kc,NULL,PLAINTEXTKEYBLOB,0,buf,&dwLen);

   len = (BYTE) dwLen;
}

到目前为止,我已经将它转换为 .NET:

    public static byte[] HashItB(string text)
    {
        byte[] textBytes = System.Text.Encoding.UTF8.GetBytes(text);
        System.Security.Cryptography.MD5CryptoServiceProvider sp = new System.Security.Cryptography.MD5CryptoServiceProvider();

        byte[] hashBytes = sp.ComputeHash(textBytes);
        System.Security.Cryptography.PasswordDeriveBytes pdb = new System.Security.Cryptography.PasswordDeriveBytes(hashBytes, new byte[0]);
        hashBytes = pdb.CryptDeriveKey("TripleDES", "SHA1", 192, hashBytes);

        // Need to export key as plain text blob here, CryptExportKey

        return (hashBytes);
    }

假设上面的代码是正确的,我的最后一步是将 CryptExportKey 函数转换为 .NET。有人可以指点我的功能或样本吗?我无法更改 C++ 方法,我需要我的 .NET 代码来匹配旧版应用程序。或者我应该放弃 .NET 方法并创建一个 C++ DLL 并调用它(由于我的小应用程序附带另一个 DLL 的额外大小,这并不疯狂),或者调用所有 Crypto 函数?

4

3 回答 3

3

.NET 方法PasswordDeriveBytes.CryptDeriveKey()等价于使用 Win32 CryptoAPI 方法对密码进行哈希处理,调用CryptDeriveKey并最终通过调用导出密钥CryptExportKey

您的 C++ 代码相当于:

byte[] textBytes = System.Text.Encoding.Default.GetBytes(text); // Default is the ANSI-code-page
System.Security.Cryptography.PasswordDeriveBytes pdb = new System.Security.Cryptography.PasswordDeriveBytes(textBytes, new byte[0]);
byte[] hashBytes = pdb.CryptDeriveKey("TripleDES", "MD5", 0, new byte[8]);

除了 .NET 代码从导出的密钥(一个 PLAINTEXTKEYBLOB 头)中删除一些头数据。对于 192 位 3DES 密钥,这是"08 02 00 00 03 66 00 00 18 00 00 00". 如果需要,您可以将其添加到 .NET 代码中。

于 2012-04-18T05:51:35.923 回答
1

PasswordDeriveBytes.CryptDeriveKey 方法已经返回派生密钥,因此无需像在 C++ 代码中那样导出密钥。

于 2012-04-18T05:28:38.657 回答
1

感谢您的帮助,如果以后有人需要阅读这篇文章,这就是我的最终结果。我确信字节数组的构建可能会更好,但在我的情况下,这段代码不需要很快,所以我只选择了我容易阅读的内容:

    public static byte[] HashIt(string text)
    {
        byte[] textBytes = System.Text.Encoding.UTF8.GetBytes(text);
        System.Security.Cryptography.PasswordDeriveBytes pdb = new System.Security.Cryptography.PasswordDeriveBytes(textBytes, new byte[0]);
        byte[] hashBytes = pdb.CryptDeriveKey("TripleDES", "MD5", 0, new byte[8]);
        byte[] head = new byte[] { 0x08,0x02, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00 };
        byte[] hashBytesWithHead = new byte[hashBytes.Length + head.Length];
        head.CopyTo(hashBytesWithHead,0);
        hashBytes.CopyTo(hashBytesWithHead,head.Length);
        return (hashBytesWithHead);
    }
于 2012-04-18T15:41:12.150 回答