使用 CryptDecrypt 解密 RijndaelManaged 加密字符串

发布于 2024-07-13 10:56:57 字数 2517 浏览 7 评论 0原文

好的,我正在尝试使用 C++ 中的 Win32 Crypto API 来解密使用 RijndaelManaged 类在 C# (.NET 2) 中加密的字符串。 但我一点运气都没有,我得到了乱码或坏数据 Win32 错误代码。 我所有的密钥、IV 和盐都匹配,我在手表中查找了这两个测试应用程序。 我已经花了所有的时间看它,但我正式被困住了。

C#

            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(GetPassPhrase(), salt, 1000);
        RijndaelManaged rijndael = new RijndaelManaged();
        rijndael.BlockSize = 128;
        rijndael.KeySize = 256;
        rijndael.Mode = CipherMode.CBC;

        rijndael.Key = pdb.GetBytes(m_KeySize);
        rijndael.IV = GetIV(iv);

        ICryptoTransform encryptor = rijndael.CreateEncryptor(); 
        MemoryStream msEncrypt = new MemoryStream();
        CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
        Byte[] encryptedBytes = null;
        Byte[] toBeEncrypted = UnicodeEncoding.Unicode.GetBytes(value);

        csEncrypt.Write(toBeEncrypted, 0, toBeEncrypted.Length);
        csEncrypt.FlushFinalBlock();
        encryptedBytes = msEncrypt.ToArray();

无论如何,这里是解密它的

                                    keyBlob.hdr.bType = PLAINTEXTKEYBLOB;
                keyBlob.hdr.bVersion = CUR_BLOB_VERSION;
                keyBlob.hdr.reserved = 0;
                keyBlob.hdr.aiKeyAlg = CALG_AES_256;
                keyBlob.cbKeySize = KEY_SIZE;
                keyBlob.rgbKeyData = &byKey[0];

                if ( CryptImportKey( hProv, (const LPBYTE) &keyBlob, sizeof(BLOBHEADER) + sizeof(DWORD) + KEY_SIZE, 0, CRYPT_EXPORTABLE, &hKey ) )
                {

                    if ( CryptSetKeyParam( hKey, KP_IV, (const BYTE *) &byIV, 0))
                    {
                        DWORD dwLen = iDestLen;
                        if ( CryptDecrypt( hKey, 0, TRUE, 0, pbyData, &dwLen))
                        {

                            if ( dwLen < (DWORD) *plOutSize)
                            {
                                memcpy_s(pbyOutput, *plOutSize, pbyData, dwLen);

                                *plOutSize = dwLen;

                                bRet = TRUE; 
                            }
                        }
                        else
                        {
                            // Log
                            DWORD dwErr = ::GetLastError();
                            int y =0;
                        }
                    }
                }

C++ 是:我成功调用 CryptAcquireContext 并且我的 C++ 执行良好。 谁能发现我的方法中的错误。 我开始感到沮丧了:(

Ok I'm trying to use the Win32 Crypto API in C++ to decrypt a string encrypted in C# (.NET 2) with the RijndaelManaged Class. But I'm having no luck at all i get jibberish or a bad data Win32 error code. All my keys, IV and salt match, I've looked in the watch for both test apps. I've spent all say looking at it and I'm officialy stuck.

Anyway here is the C#

            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(GetPassPhrase(), salt, 1000);
        RijndaelManaged rijndael = new RijndaelManaged();
        rijndael.BlockSize = 128;
        rijndael.KeySize = 256;
        rijndael.Mode = CipherMode.CBC;

        rijndael.Key = pdb.GetBytes(m_KeySize);
        rijndael.IV = GetIV(iv);

        ICryptoTransform encryptor = rijndael.CreateEncryptor(); 
        MemoryStream msEncrypt = new MemoryStream();
        CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
        Byte[] encryptedBytes = null;
        Byte[] toBeEncrypted = UnicodeEncoding.Unicode.GetBytes(value);

        csEncrypt.Write(toBeEncrypted, 0, toBeEncrypted.Length);
        csEncrypt.FlushFinalBlock();
        encryptedBytes = msEncrypt.ToArray();

The C++ to decrypt it is:

                                    keyBlob.hdr.bType = PLAINTEXTKEYBLOB;
                keyBlob.hdr.bVersion = CUR_BLOB_VERSION;
                keyBlob.hdr.reserved = 0;
                keyBlob.hdr.aiKeyAlg = CALG_AES_256;
                keyBlob.cbKeySize = KEY_SIZE;
                keyBlob.rgbKeyData = &byKey[0];

                if ( CryptImportKey( hProv, (const LPBYTE) &keyBlob, sizeof(BLOBHEADER) + sizeof(DWORD) + KEY_SIZE, 0, CRYPT_EXPORTABLE, &hKey ) )
                {

                    if ( CryptSetKeyParam( hKey, KP_IV, (const BYTE *) &byIV, 0))
                    {
                        DWORD dwLen = iDestLen;
                        if ( CryptDecrypt( hKey, 0, TRUE, 0, pbyData, &dwLen))
                        {

                            if ( dwLen < (DWORD) *plOutSize)
                            {
                                memcpy_s(pbyOutput, *plOutSize, pbyData, dwLen);

                                *plOutSize = dwLen;

                                bRet = TRUE; 
                            }
                        }
                        else
                        {
                            // Log
                            DWORD dwErr = ::GetLastError();
                            int y =0;
                        }
                    }
                }

I'm calling CryptAcquireContext successfully and my C++ is executing fine. Can anyone spot the error in my ways. It's starting to depress me know :(

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

染墨丶若流云 2024-07-20 10:56:57

好吧,我的错,我没有在 C++ 中包含 keyblob 的 Struct def,事实证明您需要带有标头的密钥的连续数据块,但我使用的是 MSDN 示例,该示例有一个指向密钥数据的指针。 这是错误的!

Ok my fault, I didn't include the Struct def for the keyblob in the C++ and it turns out you need a contigous block of data for the key with the header but I was using the MSDN example that had a pointer to the key data. Which is wrong!

菊凝晚露 2024-07-20 10:56:57

我看到您正在使用 CBC 链接模式来加密纯文本。

您确定使用相同的链接模式来解密密文吗?

(抱歉。我无法从代码中理解这一点)

I see that you are using CBC chaining mode to encrypt the plain text.

Are you sure you are using the same chaining mode to decrypt the cypher text?

(I am sorry. I am not able to understand that from the code)

执手闯天涯 2024-07-20 10:56:57

您应该检查一些事情,因为缺少一些代码(声明等):

  • 块大小 - 这通常应该与密钥大小相同,我认为它甚至可能是默认值,因为您没有在 C++ 上指定它边。 在 C# 端将其设置为 256,我想您最好也在 C++ 中明确指定它。
  • 填充 - 托管类将 PKCS7 作为默认填充,我认为它也是 cryptoAPI 函数的默认填充,但我不确定。
  • 我假设 GetPassPhrase、GetIV 等给你的密钥与你在 C++ 端使用的密钥相同?
  • 目前尚不清楚加密数据如何在程序之间传递,是否可能存在某种翻译错误? 例如base64、URL编码等。

There are a handful of things you should check, since some of the code (declarations etc) are missing:

  • Block size - this usually should be the same as key size, I think it might even be the default since you dont specify it on C++ side. Set it to 256 on C# side, I guess it best that you explicitly specify it in C++ too.
  • Padding - the managed classes have PKCS7 as their default padding, I think its the default for cryptoAPI functions too, but I'm not sure.
  • I assume that GetPassPhrase, GetIV etc give you he same keys you're using on the C++ side?
  • It's not clear how the encrypted data is passed between the programs, is it possible there is some kind of translation error? E.g. base64, URL encode, etc.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文