【问题标题】:Compare AES encryption OpenSSL versus .NET(RijndaelManaged)比较 AES 加密 OpenSSL 与 .NET(RijndaelManaged)
【发布时间】:2015-06-06 05:02:08
【问题描述】:

我需要加密一个 URL。根据 URL 的规范,它应该使用 CBC 加密模式(Rijndael)编码,使用 0 的 IV、PKCS7 填充和 128 位的密钥长度。

URL 的解密是在 .NET 环境中使用 RijndaelManaged 类完成的。我使用 OpenSSL 1.0.2a(C++ 非托管)加密并使用以下代码(来自互联网):

// ctx holds the state of the encryption algorithm so that it doesn't
// reset back to its initial state while encrypting more than 1 block.
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);

unsigned char key[] = {0x41, 0x41, 0x45, 0x43, 0x41, 0x77, 0x51, 0x46, 
                                    0x43, 0x67, 0x63, 0x49, 0x43, 0x5A, 0x6F, 0x4C };
unsigned char iv[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
assert(sizeof(key) == 16);  // AES128 key size
assert(sizeof(iv) == 16);   // IV is always the AES block size

// If data isn't a multiple of 16, the default behavior is to pad with
// n bytes of value n, where n is the number of padding bytes required
// to make data a multiple of the block size.  This is PKCS7 padding.
// The output then will be a multiple of the block size.
std::string plain("someId=007&accountNo=119955244351&user=admin&");
std::vector<unsigned char> encrypted;
size_t max_output_len = plain.length() + 16 - (plain.length() % 16);
encrypted.resize(max_output_len);

// Enc is 1 to encrypt, 0 to decrypt, or -1 (see documentation).
EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv, 1);

// EVP_CipherUpdate can encrypt all your data at once, or you can do
// small chunks at a time.
int actual_size = 0;
if( !EVP_CipherUpdate(&ctx,
                &encrypted[0], &actual_size,
                reinterpret_cast<unsigned char *>(&plain[0]), plain.size()))
{
    EVP_CIPHER_CTX_cleanup(&ctx);
}

// EVP_CipherFinal_ex is what applies the padding.  If your data is
// a multiple of the block size, you'll get an extra AES block filled
// with nothing but padding.
int final_size;
EVP_CipherFinal_ex(&ctx, &encrypted[actual_size], &final_size);
actual_size += final_size;

encrypted.resize(actual_size);

for( size_t index = 0; index < encrypted.size(); ++index )
{
    std::cout << std::hex << std::setw(2) << std::setfill('0') <<
                    static_cast<unsigned int>(encrypted[index]);
}
std::cout << "\n";

EVP_CIPHER_CTX_cleanup(&ctx);

AESWrapper aesWrapper;
std::string encryptedbase64(aesWrapper.base64encode( &encrypted[0], encrypted.size()));

我已经(显然)检查了密钥、iv 和算法 aes-cbc-128 和 afaik OpenSSL 默认使用 PKCS7 填充,但结果不匹配!

引人注目的是EVP_CipherFinal_ex 中似乎没有发生填充。填充应包含获得正确块大小所需的字节数,并用该数字填充每个字节。但它似乎充满了随机数据(或者可能是更多加密?)

此代码是否存在问题,可以解释为什么加密不“正确”? 我应该关注不正确的填充以及在这种情况下如何调试?

有什么建议吗?

【问题讨论】:

    标签: c# c++ openssl cryptography rijndael


    【解决方案1】:

    没关系。我让它工作了。解密 URL 的 C# 应用程序在密钥上使用 SHA1 哈希。在加密 URL 之前对密钥进行哈希处理后,它开始工作。

    【讨论】:

      猜你喜欢
      • 2012-11-09
      • 2014-08-22
      • 1970-01-01
      • 1970-01-01
      • 2013-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多