0

C# の Rfc2898DeriveBytes と 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¢
4

1 に答える 1

3

C++ コードの問題はciphertext変数にあります。これは base 64 データです。復号化を試みる前にバイナリにデコードしてください。

于 2013-08-08T22:33:38.867 に答える