生成大小不是16的倍数的加密数据

Generate encrypted data with size not multiple of 16

本文关键字:加密 数据      更新时间:2023-10-16

我想开发加密和解密功能。密钥大小应当至少为128比特(16字节)。

我使用了OpenSSL中的AES* api函数。但在AES*函数中有一些限制:输入数据缓冲区应该是16的倍数!

以下是我的功能:

unsigned char encrypt_aes_key[]={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
static inline int enc_array_decrypt(unsigned char *encarray, unsigned char *decarray, int size)
{
    int i;
    AES_KEY dec_key;
    unsigned char apibuf[512] = {0};
    unsigned char iv[AES_BLOCK_SIZE];
    memset(iv, 0x00, AES_BLOCK_SIZE);
    AES_set_decrypt_key(encrypt_aes_key, sizeof(encrypt_aes_key)*8, &dec_key); // Size of key is in bits
    AES_cbc_encrypt(encarray, apibuf, size, &dec_key, iv, AES_DECRYPT);
    memcpy(decarray, apibuf, size);
    return 0;
}
static inline int enc_array_encrypt(unsigned char *array, unsigned char *encarray, int size)
{
    int i;
    AES_KEY enc_key;
    unsigned char apibuf[512] = {0};
    unsigned char iv[AES_BLOCK_SIZE];
    memset(iv, 0x00, AES_BLOCK_SIZE);
    AES_set_encrypt_key(encrypt_aes_key, sizeof(encrypt_aes_key)*8, &enc_key); // Size of key is in bits
    AES_cbc_encrypt((unsigned char *)array, apibuf, size, &enc_key, iv, AES_ENCRYPT);
    memcpy(encarray, apibuf, size);
    return 0;
}

例如,如果我调用缓冲区大小为9的函数,这些函数将返回wron输出

示例:

int main(int argc, char *argv[] )
{
    char buf[9] = {0}, encbuf[9] = {0}, decbuf[9] = {0};
    strcpy(buf, argv[1]);
    enc_array_encrypt(buf, encbuf, 9);
    enc_array_decrypt(encbuf, decbuf, 9);
    printf("%s  n%sn", buf, decbuf);
    return 0;
}

程序返回:

$ ./myprogram any
any  
2�����S�

我该怎么解决?

顺便说一句,我不能强迫缓冲区是16倍的乘数大小。因为我将把我的函数集成到一个大源代码(SDK)中,在这个SDK中,我将在许多具有不同输入缓冲区大小的地方调用我的函数。

我可以使用任何其他类型的加密(AES除外),但应该支持128位长度的密钥。输入缓冲区和加密缓冲区应具有相同的大小

通常不建议在OpenSSL中直接使用AES*函数。最好使用EVP系列功能。这将允许您提供任何长度的输入缓冲区。

void log_ssl_err(const char *mes)
{
    unsigned long err;
    char errstr[1000];
    while ((err = ERR_get_error())) {
        ERR_error_string(err, errstr);
        printf("%s: %s", mes, errstr);
    }
}
int encrypt_block(const unsigned char *IV, const unsigned char *key,
                  const unsigned char *src, unsigned int srclen,
                  unsigned char *dest, unsigned int *destlen)
{
    EVP_CIPHER_CTX ctx;
    const EVP_CIPHER *cipher = EVP_get_cipherbyname("AES-256-CBC");
    int mode, len;
    if (cipher == NULL) {
        printf("Invalid keytype");
        return 0;
    }
    mode = EVP_CIPHER_mode(cipher);
    EVP_CIPHER_CTX_init(&ctx);
    if (!EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) {
        log_ssl_err("EncryptInit for cipher failed");
        return 0;
    }
    if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, IV)) {
        log_ssl_err("EncryptInit for key/IV failed");
        return 0;
    }
    len = 0;
    if (!EVP_EncryptUpdate(&ctx, dest, &len, src, srclen)) {
        log_ssl_err("EncryptUpdate for data failed");
        EVP_CIPHER_CTX_cleanup(&ctx);
        return 0;
    }
    *destlen = len;
    if (!EVP_EncryptFinal_ex(&ctx, dest + *destlen, &len)) {
        log_ssl_err("EncryptFinal failed");
        EVP_CIPHER_CTX_cleanup(&ctx);
        return 0;
    }
    *destlen += len;
    EVP_CIPHER_CTX_cleanup(&ctx);
    return 1;
}
int decrypt_block(const unsigned char *IV, const unsigned char *key,
                  unsigned char *src, unsigned int srclen,
                  unsigned char *dest, unsigned int *destlen)
{
    EVP_CIPHER_CTX ctx;
    const EVP_CIPHER *cipher = EVP_get_cipherbyname("AES-256-CBC");
    int mode, len;
    if (cipher == NULL) {
        printf("Invalid keytype");
        return 0;
    }
    mode = EVP_CIPHER_mode(cipher);
    EVP_CIPHER_CTX_init(&ctx);
    if (!EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) {
        log_ssl_err("DecryptInit for cipher failed");
        return 0;
    }
    if (!EVP_DecryptUpdate(&ctx, dest, &len, src, srclen)) {
        log_ssl_err("DecryptUpdate for data failed");
        EVP_CIPHER_CTX_cleanup(&ctx);
        return 0;
    }
    *destlen = len;
    if (!EVP_DecryptFinal_ex(&ctx, dest + *destlen, &len)) {
        log_ssl_err("DecryptFinal failed");
        EVP_CIPHER_CTX_cleanup(&ctx);
        return 0;
    }
    *destlen += len;
    EVP_CIPHER_CTX_cleanup(&ctx);
    return 1;
}