使用C / C ++和openssl处理单个AES-128-ECB块

时间:2013-05-15 08:54:58

标签: c++ c openssl aes ecb

我想使用 AES-128-ECB 密码对单个16字节数据块进行解码和解码。 首先,我通过 openssl 命令行实用程序使用ASCII 16字符串“a_key_simple_key”作为键,并使用ASCII 16字符串“1234567890uvwxyz”作为消息。命令行实用程序将十六进制字符串“142f 7d9e ad8c 0682 30e0 f165 a52f f789”打印为加密消息,然后将其成功解码回原始消息,如下所示:

$ echo -n "1234567890uvwxyz" | openssl aes-128-ecb -K $(echo -n "a_key_simple_key" | xxd -ps) -nopad | xxd
0000000: 142f 7d9e ad8c 0682 30e0 f165 a52f f789  ./}.....0..e./..
$ echo "142f 7d9e ad8c 0682 30e0 f165 a52f f789" | xxd -r -ps | openssl aes-128-ecb -d -K $(echo -n "a_key_simple_key" | xxd -ps) -nopad 
1234567890uvwxyz

现在我写了一个简短的C ++程序,它应该做同样的事情。它不起作用。有两个问题:

  1. 编码部分的输出是32个字节长而不是16个字节(这32个字节的前半部分恰好是我期望看到的加密文本)
  2. 解码部分在完成步骤中失败,并显示以下openssl消息:
  3. 错误:06065064:数字信封例程:EVP_DecryptFinal_ex:解密不良

    我怀疑这两个问题都以某种方式与填充相关联,但我不明白究竟有什么问题以及如何解决它。以下是该计划的完整输出:

    $ g++ -Wall -g ssl-aes-128-ecb.c++ -lcrypto -lssl && ./a.out 2>&1 | less
    ENCODING: FAIL
    ENCODING: 1234567890uvwxyz --> ^T/}<9E><AD><8C>^F<82>0<E0><F1>e<A5>/<F7><89>^X<A0>P<U+DACE>R<F8>a^R^A<8A><97>GF*
    error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
    Aborting in u_string decode(u_string, u_string) at ssl-aes-128-ecb.c++:56
    

    这是C ++程序本身(带行号):

    01 #include <string>
    02 #include <iostream>
    03 #include <openssl/evp.h>
    04 #include <openssl/err.h>
    05 #include <openssl/ssl.h>
    06 #define ABORT() (fprintf(stderr, "%s\nAborting in %s at %s:%d\n", ERR_error_string(ERR_get_error(), NULL), __PRETTY_FUNCTION__, __FILE__, __LINE__), abort(), 0)
    07
    08 typedef std::basic_string<unsigned char> u_string;
    09 static u_string encode(u_string key, u_string data);
    10 static u_string decode(u_string key, u_string data);
    11
    12 // echo -n "1234567890uvwxyz" | openssl aes-128-ecb -K $(echo -n "a_key_simple_key" | xxd -ps) -nopad | xxd
    13 // echo "142f 7d9e ad8c 0682 30e0 f165 a52f f789" | xxd -r -ps | openssl aes-128-ecb -d -K $(echo -n "a_key_simple_key" | xxd -ps) -nopad
    14
    15 int main()
    16 {
    17   SSL_load_error_strings();
    18
    19   u_string key = (unsigned char *) "a_key_simple_key";
    20   u_string clear_text = (unsigned char *) "1234567890uvwxyz";
    21   u_string secret_txt = (unsigned char *) "\x14\x2f" "\x7d\x9e" "\xad\x8c" "\x06\x82" "\x30\xe0" "\xf1\x65" "\xa5\x2f" "\xf7\x89";
    22
    23   std::cerr << "ENCODING: " << (encode(key, clear_text)==secret_txt ? "ok" : "FAIL") << std::endl;
    24   std::cerr << "ENCODING: " << (char*)clear_text.c_str() << " --> " << (char*)encode(key, clear_text).c_str() << std::endl;
    25   std::cerr << "DECODING: " << (decode(key, secret_txt)==clear_text ? "ok" : "FAIL") << std::endl;
    26   std::cerr << "DECODING: " << (char*)secret_txt.c_str() << " --> " << (char*)decode(key, secret_txt).c_str() << std::endl;
    27
    28   return 0;
    29 }
    30
    31 static u_string encode(u_string key, u_string data)
    32 {
    33   EVP_CIPHER_CTX ctx;
    34   EVP_CIPHER_CTX_init(&ctx);
    35   EVP_CIPHER_CTX_set_padding(&ctx, false);
    36   EVP_EncryptInit_ex (&ctx, EVP_aes_128_ecb(), NULL, key.c_str(), NULL);
    37   unsigned char buffer[1024], *pointer = buffer;
    38   int outlen;
    39   EVP_EncryptUpdate (&ctx, pointer, &outlen, data.c_str(), data.length()) or ABORT();
    40   pointer += outlen;
    41   EVP_EncryptFinal_ex(&ctx, pointer, &outlen) or ABORT();
    42   pointer += outlen;
    43   return u_string(buffer, pointer-buffer);
    44 }
    45
    46 static u_string decode(u_string key, u_string data)
    47 {
    48   EVP_CIPHER_CTX ctx;
    49   EVP_CIPHER_CTX_init(&ctx);
    50   EVP_CIPHER_CTX_set_padding(&ctx, false);
    51   EVP_DecryptInit_ex (&ctx, EVP_aes_128_ecb(), NULL, key.c_str(), NULL);
    52   unsigned char buffer[1024], *pointer = buffer;
    53   int outlen;
    54   EVP_DecryptUpdate (&ctx, pointer, &outlen, data.c_str(), data.length()) or ABORT();
    55   pointer += outlen;
    56   EVP_DecryptFinal_ex(&ctx, pointer, &outlen) or ABORT();
    57   pointer += outlen;
    58   return u_string(buffer, pointer-buffer);
    59 }
    

1 个答案:

答案 0 :(得分:4)

好吧,我似乎弄清楚了什么是错的:

必须在EVP_CIPHER_CTX_set_padding()电话

之后进行

EVP_DecryptInit_ex()来电

因此解决方案是交换50/51和35/36行。