Rfc2898DeriveBytes 是否等同于 PKCS5_PBKDF2_HMAC_SHA1
本文关键字:PBKDF2 SHA1 HMAC PKCS5 是否 等同于 Rfc2898DeriveBytes | 更新日期: 2023-09-27 18:26:53
Rfc2898C#中的DeriveBytes和C++中的PKCS5_PBKDF2_HMAC_SHA1应该是同一个函数(PBKDF2(。 但是当我尝试用 C# 加密消息并在 C++ 中解密时,密码会有所不同。 我将相同的信息(密码,IV和盐(放在两侧。我编译了一些更简单的例子来说明正在发生的事情。 我犯了一个错误,还是我需要在某个地方使用不同的库?
C# 加密:
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
public class RijndaelSimpleTest
{
[STAThread]
static void Main(string[] args)
{
string plainText = "Hello, World!";
string passPhrase = "testtesttesttesttesttest";
string initVector = "6543210987654321";
string saltValue = "1234567890123456";
int passwordIterations = 10000;
int keySize = 32;
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations);
byte[] keyBytes = password.GetBytes(keySize);
string debugPassword = Convert.ToBase64String(keyBytes);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
string encyptText = Convert.ToBase64String(cipherTextBytes);
string cipherText = initVector + saltValue + encyptText;
Console.WriteLine(String.Format("Plaintext : {0}", plainText));
Console.WriteLine(String.Format("passPhrase : {0}", passPhrase));
Console.WriteLine(String.Format("initVector : {0}", initVector));
Console.WriteLine(String.Format("saltValue : {0}", saltValue));
Console.WriteLine(String.Format("passwordIterations : {0}", passwordIterations));
Console.WriteLine(String.Format("keySize : {0}", keySize));
Console.WriteLine(String.Format("password : {0}", debugPassword));
Console.WriteLine(String.Format("EncryptedText : {0}", encyptText));
Console.WriteLine(String.Format("EncryptedText+IV+SALT : {0}", cipherText));
}
}
输出
Plaintext : Hello, World!
passPhrase : testtesttesttesttesttest
initVector : 6543210987654321
saltValue : 1234567890123456
passwordIterations : 10000
keySize : 32
password : uu1FmPoEROlTBOvilXnIHG64uS56i3f4br/RZ1d49YE=
EncryptedText : rVGIwm/WH9tw/SiN+iXw0Q==
EncryptedText+IV+SALT : 65432109876543211234567890123456rVGIwm/WH9tw/SiN+iXw0Q==
C++ 输出:
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <stdio.h>
#include <string>
#include <iostream>
const unsigned char* convertString(const std::string& s){
unsigned char * bytes = new unsigned char[s.size() + 1];
std::copy(s.begin(), s.end(), bytes);
bytes[s.size()] = ''0';
return(bytes);
}
int main(int argc, char** argv) {
const char passPhrase[] = "testtesttesttesttesttest";
std::string ExpectedPlaintext = "Hello, World!";
int passwordIterations = 10000;
int keySize = 32;
std::string EncryptedText = "65432109876543211234567890123456rVGIwm/WH9tw/SiN+iXw0Q==";
std::string ExpectedIV = "6543210987654321";
std::string ExpectedSalt = "1234567890123456";
std::string ExpectedCipherText = "rVGIwm/WH9tw/SiN+iXw0Q==";
std::string Expectedpassword = "uu1FmPoEROlTBOvilXnIHG64uS56i3f4br/RZ1d49YE=";
const unsigned char *initVector = convertString(EncryptedText.substr(0,16));
const unsigned char *saltValue = convertString(EncryptedText.substr(16,16));
const unsigned char *ciphertext = convertString(EncryptedText.substr(16+16));
unsigned char password[keySize+16+1];
if (PKCS5_PBKDF2_HMAC_SHA1(passPhrase, strlen(passPhrase),
saltValue, strlen((char*)saltValue), passwordIterations,
keySize+16, password) != 1) {
std::cout << "Could not derive password" << std::endl;
return -1;
}
password[keySize] = ''0';
int p_len = keySize;
int f_len = 0;
unsigned char *plaintext = (unsigned char*)malloc(p_len + AES_BLOCK_SIZE);
EVP_CIPHER_CTX d_ctx;
EVP_CIPHER_CTX_init(&d_ctx);
EVP_DecryptInit_ex(&d_ctx, EVP_aes_256_cbc(), NULL, password, initVector);
EVP_DecryptInit_ex (&d_ctx, NULL, NULL, NULL, NULL);
EVP_DecryptUpdate (&d_ctx, plaintext, &p_len, ciphertext, keySize);
EVP_DecryptFinal_ex(&d_ctx, plaintext+p_len, &f_len);
keySize = p_len + f_len;
std::cout << "EncryptedText : " << EncryptedText << std::endl;
std::cout << "passPhrase : " << passPhrase << std::endl;
std::cout << "passwordIterations: " << passwordIterations << std::endl;
std::cout << "keySize : " << keySize << std::endl;
std::cout << "ExpectedIV : " << ExpectedIV << std::endl;
std::cout << "initVector : " << initVector << std::endl;
std::cout << "ExpectedSalt : " << ExpectedSalt << std::endl;
std::cout << "saltValue : " << saltValue << std::endl;
std::cout << "ExpectedCipherText: " << ExpectedCipherText << std::endl;
std::cout << "ciphertext : " << ciphertext << std::endl;
std::cout << "Expectedpassword : " << Expectedpassword << std::endl;
std::cout << "password : " << password << std::endl;
std::cout << "ExpectedPlaintext : " << ExpectedPlaintext << std::endl;
std::cout << "plaintext : " << plaintext << std::endl;
EVP_CIPHER_CTX_cleanup(&d_ctx);
delete[] plaintext;
delete[] initVector;
delete[] saltValue;
delete[] ciphertext;
return 0;
}
哪些输出:
EncryptedText : 65432109876543211234567890123456rVGIwm/WH9tw/SiN+iXw0Q==
passPhrase : testtesttesttesttesttest
passwordIterations: 10000
keySize : 16
ExpectedIV : 6543210987654321
initVector : 6543210987654321
ExpectedSalt : 1234567890123456
saltValue : 1234567890123456
ExpectedCipherText: rVGIwm/WH9tw/SiN+iXw0Q==
ciphertext : rVGIwm/WH9tw/SiN+iXw0Q==
Expectedpassword : uu1FmPoEROlTBOvilXnIHG64uS56i3f4br/RZ1d49YE=
password : ºíEúDéSëâyÈn¸¹.zwøn¿ÑgWxõ
ExpectedPlaintext : Hello, World!
plaintext : ÊÁMþ±B¯ÍN'¤ä+èû~OÂ(H¢
C++代码中的问题在于ciphertext
变量:它是 base 64 数据。在尝试解密之前将其解码为二进制文件。