简体   繁体   English

Rfc2898DeriveBytes是否等于PKCS5_PBKDF2_HMAC_SHA1?

[英]Is Rfc2898DeriveBytes equivalent to PKCS5_PBKDF2_HMAC_SHA1?

Rfc2898DeriveBytes in c# and PKCS5_PBKDF2_HMAC_SHA1 in C++ are supposed to be the same function ( PBKDF2 ). c#中的Rfc2898DeriveBytes和C ++中的PKCS5_PBKDF2_HMAC_SHA1应该具有相同的功能( PBKDF2 )。 but when I tried to encrypt a message in c# and decrypt it in c++, the password comes out different. 但是,当我尝试在c#中加密消息并在c ++中解密消息时,密码出现了不同。 I am putting the same information (passphrase, IV,and salt) in both sides. 我在双方都输入了相同的信息(密码,IV和盐)。 I have compiled some simpler examples to show what is going on. 我已经汇编了一些更简单的示例来说明发生了什么。 Am I making a mistake, or do I need to use a different library somewhere? 我是在犯错误,还是需要在其他地方使用其他库?

c# encryption: 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));
    }
}

Outputs 产出

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++ Output: 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;
}

Which outputs: 哪个输出:

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¢

Your problem in your C++ code is with your ciphertext variable: It's base 64 data. C ++代码中的问题是ciphertext变量:基数为64的数据。 Decode it to binary before attempting to decrypt it. 尝试将其解密之前,将其解码为二进制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM