微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

解密 RijndaelManaged in C++ (CNG)

如何解决解密 RijndaelManaged in C++ (CNG)

下面的C#代码输出0123456789012345678901234567890123456789:

        static void Main(string[] args)
        {

            byte[] salt = Encoding.ASCII.GetBytes("saltycrack");
            Console.WriteLine(Decrypt("NpN45cs2+bVLtEgp6ZmBmmHLH89aFdHIbDjhstTK0Vb1VMr7jBsliKD9siQGGxGS","pass",salt));
        }

        public static string Decrypt(string encryptedText,string encryptionPassword,byte[] salt)
        {
            var algorithm = GetAlgorithm(encryptionPassword,salt);
            using (ICryptoTransform decryptor = algorithm.CreateDecryptor(algorithm.Key,algorithm.IV))
            {
                byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
                return Encoding.UTF8.GetString(InMemoryCrypt(encryptedBytes,decryptor));
            }
        }
        private static byte[] InMemoryCrypt(byte[] data,ICryptoTransform transform)
        {
            MemoryStream memory = new MemoryStream();
            using (Stream stream = new CryptoStream(memory,transform,CryptoStreamMode.Write))
            {
                stream.Write(data,data.Length);
            }
            return memory.ToArray();
        }
        private static RijndaelManaged GetAlgorithm(string encryptionPassword,byte[] salt)
        {
            var key = new Rfc2898DeriveBytes(encryptionPassword,salt);
            var algorithm = new RijndaelManaged();
            algorithm.Key = key.GetBytes(algorithm.KeySize / 8);
            algorithm.IV = key.GetBytes(algorithm.BlockSize / 8);
            return algorithm;
        }

我想在 C++ 中使用 Microsoft CNG 进行相同的解密:

int main(int argc,char** argv)
{
    auto salt = std::string("saltycrack");
    auto pass = std::string("pass");
    std::string cipher_text = base64_decode("NpN45cs2+bVLtEgp6ZmBmmHLH89aFdHIbDjhstTK0Vb1VMr7jBsliKD9siQGGxGS");
    NTSTATUS bcryptResult = 0;

    BCRYPT_ALG_HANDLE alg = 0;
    assert(BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&alg,BCRYPT_AES_ALGORITHM,0)));

    BCRYPT_ALG_HANDLE prf = NULL;
    assert(BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&prf,BCRYPT_SHA1_ALGORITHM,nullptr,BCRYPT_ALG_HANDLE_HMAC_FLAG)));
        
    auto key_len = 32;
    ULONGLONG iter = 1000;
    ULONG kbh_len = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + key_len;
    BCRYPT_KEY_DATA_BLOB_HEADER* kbh = (BCRYPT_KEY_DATA_BLOB_HEADER*)malloc(kbh_len);
    assert(BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(prf,(PUCHAR)pass.data(),pass.size(),(PUCHAR)salt.data(),salt.size(),iter,(uint8_t*)(kbh + 1),key_len,0)));

    kbh->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
    kbh->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
    kbh->cbKeyData = key_len;
    DWORD key_obj_len;
    ULONG got;
    assert(BCRYPT_SUCCESS(BCryptGetProperty(alg,BCRYPT_OBJECT_LENGTH,(PBYTE)&key_obj_len,sizeof(DWORD),&got,0)));
    uint8_t* key_obj = new uint8_t[key_obj_len];
    BCRYPT_KEY_HANDLE key = 0;

    assert(BCRYPT_SUCCESS(BCryptImportKey(alg,NULL,BCRYPT_KEY_DATA_BLOB,&key,key_obj,key_obj_len,(PUCHAR)kbh,kbh_len,0)));

    {
        std::wstring mode = BCRYPT_CHAIN_MODE_CBC;
        BYTE* ptr = reinterpret_cast<BYTE*>(const_cast<wchar_t*>(mode.data()));
        ULONG size = static_cast<ULONG>(sizeof(wchar_t) * (mode.size() + 1));
        assert(BCRYPT_SUCCESS(BCryptSetProperty(alg,BCRYPT_CHAINING_MODE,ptr,size,0)));
    }
    DWORD bytes_done = 0;
    DWORD block_len = 0;
    assert(BCRYPT_SUCCESS(BCryptGetProperty(alg,BCRYPT_BLOCK_LENGTH,(BYTE*)&block_len,sizeof(block_len),&bytes_done,0)));
    auto iv = std::vector<uint8_t>(block_len);
    ULONG bufferlen = 0;
    assert(BCRYPT_SUCCESS(BCryptDecrypt(key,(PUCHAR)cipher_text.data(),cipher_text.size(),(PUCHAR)iv.data(),iv.size(),&bufferlen,BCRYPT_BLOCK_PADDING)));
    auto plaintext = std::string(bufferlen,'\0');
    assert(BCRYPT_SUCCESS(BCryptDecrypt(key,(PUCHAR)plaintext.data(),plaintext.size(),BCRYPT_BLOCK_PADDING)));
   
    std::cout << plaintext << "\n";
    return 0;
}

C++ 程序输出#♂b⌡Cεk╘┴╟AÑ@├0⌠678901234567890123456789。 看起来解密部分成功,这没有意义。

我是否需要对解密后的数据进行解码,或者某处是否存在数据损坏?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。