如何解决解密 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 举报,一经查实,本站将立刻删除。