openssl aes api 記錄

DemoCode1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/evp.h>
#include <openssl/aes.h>

int main(void)
{
    unsigned char userkey[EVP_MAX_KEY_LENGTH];
    unsigned char iv[EVP_MAX_IV_LENGTH];
    //    unsigned char *date = (unsigned char *)malloc(AES_BLOCK_SIZE*3);
    int dateLen = 35;														//******* [1] *******
    unsigned char *date = (unsigned char *)malloc(dateLen);
    unsigned char *encrypt = (unsigned char *)malloc(AES_BLOCK_SIZE*6);
    unsigned char *plain = (unsigned char *)malloc(AES_BLOCK_SIZE*6);
    EVP_CIPHER_CTX ctx;
    int ret;
    int tlen = 0;
    int mlen = 0;
    int flen = 0;

    memset((void*)userkey, 'k', EVP_MAX_KEY_LENGTH);
    memset((void*)iv, 'i', EVP_MAX_IV_LENGTH);
    memset((void*)date, 'p', dateLen);
    memset((void*)encrypt, 'H', AES_BLOCK_SIZE*6);
    memset((void*)plain, 0, AES_BLOCK_SIZE*6);

    /*初始化ctx*/
    EVP_CIPHER_CTX_init(&ctx);

    /*指定加密算法及key和iv(此處IV沒有用)*/
    ret = EVP_EncryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, userkey, iv);
    if(ret != 1) {
        printf("EVP_EncryptInit_ex failed\n");
        exit(-1);
    }

    /*禁用padding功能*/
    EVP_CIPHER_CTX_set_padding(&ctx, 0);								//******* [2] *******
    
    /*進行加密操作*/
    ret = EVP_EncryptUpdate(&ctx, encrypt, &mlen, date, dateLen);		//******* [3] *******
    if(ret != 1) {
        printf("EVP_EncryptUpdate failed\n");
        exit(-1);
    }
    /*結束加密操作*/
    ret = EVP_EncryptFinal_ex(&ctx, encrypt+mlen, &flen);				//******* [4] *******
    if(ret != 1) {
        printf("EVP_EncryptFinal_ex failed\n");
        exit(-1);
    }

    tlen = mlen + flen;													//******* [5] *******	

    tlen = 0;
    mlen = 0;
    flen = 0;

    EVP_CIPHER_CTX_cleanup(&ctx);
    EVP_CIPHER_CTX_init(&ctx);

    ret = EVP_DecryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, userkey, iv);
    if(ret != 1) {
        printf("EVP_DecryptInit_ex failed\n");
        exit(-1);
    }

    EVP_CIPHER_CTX_set_padding(&ctx, 0);
    ret = EVP_DecryptUpdate(&ctx, plain, &mlen, encrypt, AES_BLOCK_SIZE*3);
    if(ret != 1) {
        printf("EVP_DecryptUpdate failed\n");
        exit(-1);
    }

    ret = EVP_DecryptFinal_ex(&ctx, plain+mlen, &flen);
    if(ret != 1) {
        printf("EVP_DecryptFinal_ex failed\n");
        exit(-1);
    }
    /*對比解密後與原數據是否一致*/
    if(!memcmp(plain, date, dateLen)) {
        printf("test success\n");
    } else {
        printf("test failed\n");
    }

    printf("encrypt: ");
    int i;
    for(i = 0; i < AES_BLOCK_SIZE*3+4; i ++){
        printf("%.2x ", encrypt[i]);
        if((i+1)%32 == 0){
            printf("\n");
        }
    }
    printf("\n");
    for(i = 0; i < dateLen; i ++){
        printf("%.2x ", date[i]);
        if((i+1)%32 == 0){
            printf("\n");
        }
    }
    printf("\n");
    for(i = 0; i < AES_BLOCK_SIZE*3; i ++){
        printf("%.2x ", plain[i]);
        if((i+1)%32 == 0){
            printf("\n");
        }
    }
    printf("\n");
#endif

    return 0;
}

本文中有一個很不明白的點,共有三個len變量,分別是tlen,mlen,flen,分別是什麼作用
基於這個問題,在[1]處,重新指定了源數據長度爲35,

  1. debug發現:
  • 當[2]處設置禁用padding時:
    在[3]處,mlen值爲32;
    在[4]處,flen值爲0,並且EVP_EncryptFinal_ex返回0,即失敗。
  • 當[2]處註釋,則:
    [3] mlen值爲32;
    [4] flen值爲16;
    [5] tlen值爲48。
  1. 綜上所述,結合Openssl Manpage

If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts the “final” data, that is any data that remains in a partial block. It uses standard block padding (aka PKCS padding) as described in the NOTES section, below. The encrypted final data is written to out which should have sufficient space for one cipher block. The number of bytes written is placed in outl. After this function is called the encryption operation is finished and no further calls to EVP_EncryptUpdate() should be made.
If padding is disabled then EVP_EncryptFinal_ex() will not encrypt any more data and it will return an error if any data remains in a partial block: that is if the total data length is not a multiple of the block size.

可得:若禁用padding,則需要確認加密源數據爲16字節的整數倍,否則最後生於不足16字節的數據將不加密;如果使用padding,則末尾不足16字節,openssl將做補齊。


DemoCode2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章