使用C 中的OpenSSL使用AES128加密字符串



我在使用OpenSSL库中生成的加密消息的最后字符和AES 128算法在CBC模式下遇到问题,这些是我正在使用的数据:

Message in Hex = "7b22494443223a2232363930393439376434222c22444553223a2256656e74616d656e7564656f222c22414d4f223a3530302c22444154223a313530383233303035383730362c22524546223a302c22434f4d223a312c22545950223a31392c2276223a7b224e414d223a2252616661656c56616c656e7a75656c614172656e6173222c22414343223a2235383732313233343536373836303132222c2242414e223a34303132372c22545943223a332c22444556223a22353532373139323132382f30227d7da"
Key128 in Hex = "dadf11e74d014a62d73ccadd9591442a"
Initialization Vector in Hex = "cab9da8940cd7dc9510c7249fe47c6e6"

这是我正在使用的代码:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <math.h>
#include <assert.h>
#include <stdint.h>
#include <stdbool.h>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <locale>
#include <openssl/aes.h>
#include <openssl/des.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
using namespace std;
/* AES key for Encryption and Decryption */
const static unsigned char aes_key[16]={0xda, 0xdf, 0x11, 0xe7, 0x4d, 0x01, 0x4a, 0x62, 0xd7, 0x3c, 0xca, 0xdd, 0x95, 0x91, 0x44, 0x2a};
/* Print Encrypted and Decrypted data packets */
void print_data(const char *tittle, const void* data, int len)
{
    printf("%s : ",tittle);
    const unsigned char * p = (const unsigned char*)data;
    int i = 0;
    for (; i<len; ++i)
    {
        printf("%02X ", *p++);
    }
    printf("n");
}
int main( )
{
    /* Input data to encrypt */
    unsigned char enc_out[235]={0x7b, 0x22, 0x49, 0x44, 0x43, 0x22, 0x3a, 0x22, 0x32, 0x36, 0x39, 0x30, 0x39, 0x34, 0x39, 0x37, 0x64, 0x34, 0x22, 0x2c, 0x22, 0x44, 0x45, 0x53, 0x22, 0x3a, 0x22, 0x56, 0x65, 0x6e, 0x74, 0x61, 0x6d, 0x65, 0x6e, 0x75, 0x64, 0x65, 0x6f, 0x22, 0x2c, 0x22, 0x41, 0x4d, 0x4f, 0x22, 0x3a, 0x35, 0x30, 0x30, 0x2c, 0x22, 0x44, 0x41, 0x54, 0x22, 0x3a, 0x31, 0x35, 0x30, 0x38, 0x32, 0x33, 0x30, 0x30, 0x35, 0x38, 0x37, 0x30, 0x36, 0x2c, 0x22, 0x52, 0x45, 0x46, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x43, 0x4f, 0x4d, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x54, 0x59, 0x50, 0x22, 0x3a, 0x31, 0x39, 0x2c, 0x22, 0x76, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x41, 0x4d, 0x22, 0x3a, 0x22, 0x52, 0x61, 0x66, 0x61, 0x65, 0x6c, 0x56, 0x61, 0x6c, 0x65, 0x6e, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x22, 0x2c, 0x22, 0x41, 0x43, 0x43, 0x22, 0x3a, 0x22, 0x35, 0x38, 0x37, 0x32, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x36, 0x30, 0x31, 0x32, 0x22, 0x2c, 0x22, 0x42, 0x41, 0x4e, 0x22, 0x3a, 0x34, 0x30, 0x31, 0x32, 0x37, 0x2c, 0x22, 0x54, 0x59, 0x43, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x44, 0x45, 0x56, 0x22, 0x3a, 0x22, 0x35, 0x35, 0x32, 0x37, 0x31, 0x39, 0x32, 0x31, 0x32, 0x38, 0x2f, 0x30, 0x22, 0x7d, 0x7d, 0xa};
    /* Init vector */
    unsigned char iv[16]={0xca, 0xb9, 0xda, 0x89, 0x40, 0xcd, 0x7d, 0xc9, 0x51, 0x0c, 0x72, 0x49, 0xfe, 0x47, 0xc6, 0xe6};
    //memset(iv, 0x00, AES_BLOCK_SIZE);
    /* Buffers for Encryption and Decryption */
    unsigned char dec_out[400];
    unsigned char aux_out[400];
    memset(dec_out, 0, sizeof(dec_out));
    memset(aux_out, 0, sizeof(aux_out));
    /* AES-128 bit CBC Encryption */
    AES_KEY enc_key, dec_key;
    AES_set_encrypt_key(aes_key, sizeof(aes_key)*8, &enc_key);
    AES_cbc_encrypt(enc_out, dec_out, sizeof(enc_out), &enc_key, iv, AES_ENCRYPT);
    /* AES-128 bit CBC Decryption */
    memset(iv, 0x00, AES_BLOCK_SIZE); // don't forget to set iv vector again, else you can't decrypt data properly
    AES_set_decrypt_key(aes_key, sizeof(aes_key)*8, &dec_key); // Size of key is in bits
    AES_cbc_encrypt(dec_out, aux_out, sizeof(enc_out), &dec_key, iv, AES_DECRYPT);
    /* Printing and Verifying */
    print_data("n Original ",enc_out, sizeof(enc_out)); // you can not print data as a string, because after Encryption its not ASCII
    print_data("n Encrypted",dec_out, sizeof(enc_out));
    print_data("n Decrypted",aux_out, sizeof(dec_out));
    return 0;
}

显然只有链的末端是不正确的(最后32个字符(,其余的很好,我已经研究了一些,一切都指向文本的填充类型,但根据我的方式阅读它已经用PKCS5填充了(实际上是我需要的填充(,所以我看不到错误是什么。

The Correct Encryption = EFC063DD33406D424D359809695D0B1E2D65027E803962C6A115DF7CCABEEB0C8C358830E556ED23943FA4F02E6461D235EF913CFCE5519F7CE2279DD07D3C4054D045827D5D7D9FE94DA3C5B718A24E79539B3FFC1E68E4C3FF441EEA176F61EE3D7B33B622E3069D95815F6407FBC79342BB972A2DDE4E50FDE9302BDE4409B7D2BD388AB6A043B9EF236D982937D8537F954564FF4134BD8A6EAB994FE4C29E9DC4E54D53A561A4688C45C90961EDB1763B6EF6C86B593C7E16FDF35C49CE16B1E6948BB1EAE6A8692326A019960B
The Output of the Program = EFC063DD33406D424D359809695D0B1E2D65027E803962C6A115DF7CCABEEB0C8C358830E556ED23943FA4F02E6461D235EF913CFCE5519F7CE2279DD07D3C4054D045827D5D7D9FE94DA3C5B718A24E79539B3FFC1E68E4C3FF441EEA176F61EE3D7B33B622E3069D95815F6407FBC79342BB972A2DDE4E50FDE9302BDE4409B7D2BD388AB6A043B9EF236D982937D8537F954564FF4134BD8A6EAB994FE4C29E9DC4E54D53A561A4688C45C90961EDB1763B6EF6C86B593C7E16FDF35C49CE608E3F73FC8E3DDF1D3BCF40B3DFACD00B732A9FCC10F6E0FB18E126A1C21A082D7A4F053F131A9329474D

我了解该代码有很多改进,但我并不是在考虑解密,但是目前我不需要它。

AES_cbc_encrypt使用低级别的原始词进行加密。它没有执行任何形式的填充。这是AES CBC代码直接调用的基础CBC源代码的链接:https://github.com/openssl/openssl/openssl/blob/master/master/crypto/modes/modes/modes/cbc128.c-完全没有指示。

真正的问题是为什么您会使用未描述的,低级别实现函数,而不是OpenSSL本身提倡的EVP API。您可能会认为较低级别的原始词的性能更高,但是如果例如,情况可能并非如此。AES-NI被部署;无论如何,与密码本身相比,呼叫开销将是最小的。

enc_out -array是235个字节的尺寸,但仅是200个字节的初始化 equinalized emblicity 0x00值初始化。这对应于长度为240字节的密文(= 15 x 16字节(。因此,当前代码返回一个密文,长度为240个字节,其最后三个块为:

608E3F73FC8E3DDF1D3BCF40B3DFACD0 0B732A9FCC10F6E0FB18E126A1C21A08 2D7A4F053F131A9329474DE44DA772BC

这对应于带有0x00值的隐式填充。在发布的密文中缺少最后5个字节,这是因为授权的长度(而不是密文的长度(用于输出。

很可能只能加密前200个字节。这将对应于208个字节(= 13 x 16个字节(长度的密文,这仅仅是预期 ciphertext的长度。为此,必须将enc_out阵列的大小从235降低到200,甚至更好,根本不应明确指定大小。

然后生成一个两个块,但与其他相同的密文生成,这与仅在最后一个区块中与预期 ciphertext不同,现在仅由缺失的pkcs7-padding引起。

最新更新