OpenSSL中AES加密的用法


《OpenSSL中AES加密的用法》
作者: 游藍海
原文鏈接: http://blog.csdn.net/you_lan_hai/article/details/50992719
轉載請注明出處

使用API的時候,需要特別小心數據長度,我在初次使用的時候簡直被弄的暈頭轉向,遂作此文留個備忘。一般沒有指定長度的參數,默認都是16(AES_BLOCK_SIZE)個字節。輸出數據的長度一般都是16字節的倍數,否則會出現數組越界訪問。
以下API中,encrypt表示加密,decrypt表示解密。

1.生成加密/解密的Key

int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
                        AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
                        AES_KEY *key);

參數說明:

參數名稱 描述
userKey 用戶指定的密碼。注意:只能是16、24、32字節。如果密碼字符串長度不夠,可以在字符串末尾追加一些特定的字符,或者重復密碼字符串,直到滿足最少的長度。
bits 密碼位數。即userKey的長度 * 8,只能是128、192、256位。
key 向外輸出參數。

如果函數調用成功,返回0,否則是負數。

2.使用AES加密/解密

void AES_encrypt(const unsigned char *in, unsigned char *out,
                 const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out,
                 const AES_KEY *key);

參數說明:

參數名稱 描述
in 輸入數據。必須是16字節。
out 輸出數據。必須是16字節。
key 使用AES_set_encrypt/decrypt_key生成的Key。

AES_encrypt/AES_decrypt一次只處理16個字節。如果輸入數據較長,你需要使用循環語句,每16個字節處理一次,直到所有數據處理完畢。如果數據不足16字節,可以用0填充至16字節。

3.使用AES CBC加密/解密

void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
                     size_t length, const AES_KEY *key,
                     unsigned char *ivec, const int enc);

參數說明:

參數名稱 描述
in 輸入數據。長度任意。
out 輸出數據。能夠容納下輸入數據,且長度必須是16字節的倍數。
length 輸入數據的實際長度。
key 使用AES_set_encrypt/decrypt_key生成的Key。
ivec 可讀寫的一塊內存。長度必須是16字節。
enc 是否是加密操作。AES_ENCRYPT表示加密,AES_DECRYPT表示解密。

這個函數比AES_encrypt多了一個ivec參數,ivec的內容可以任意指定,但是加密和解密操作必須使用同樣的數據。在AES_cbc_encrypt底層,實際上是每16個字節做一次處理,先和ivec做異或運算,然后調用AES_encrypt函數進行加密。
AES_cbc_encrypt在加密的過程中會修改ivec的內容,因此ivec參數不能是一個常量,而且不能在傳遞給加密函數后再立馬傳遞給解密函數,必須重新賦值之后再傳遞給解密函數。

關於輸出數據的長度
輸出數據緩沖區的長度必須是16字節的倍數,加密完成后,比輸入長度多出來的輸出數據是不可以丟棄的。因此,存檔的時候,需要記錄原始數據的長度

關於輸入數據的長度不必是16字節的倍數(做個備忘):
下面是AES_cbc_encrypt函數的底層實現代碼

    ... 
    //處理16字節倍數的數據
    while (len >= 16) {
            for (n = 0; n < 16; ++n)
                out[n] = in[n] ^ iv[n];
            (*block) (out, out, key); //調用AES_encrypt處理數據
            iv = out;
            len -= 16;
            in += 16;
            out += 16;
        }
    //當數據小於16字節的時候,進入下面的循環
    while (len) { 
        for (n = 0; n < 16 && n < len; ++n)
            out[n] = in[n] ^ iv[n];
        for (; n < 16; ++n)
            out[n] = iv[n]; //使用ivec補齊不足16字節的部分
        (*block) (out, out, key); //調用AES_encrypt處理數據
        iv = out;
        if (len <= 16)
            break;
        len -= 16;
        in += 16;
        out += 16;
    }

4.結尾

其他加密函數我還沒有用過,在此就不繼續列舉了,但是參數跟上面幾個相似,弄明白上面的就不成問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM