《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.結尾
其他加密函數我還沒有用過,在此就不繼續列舉了,但是參數跟上面幾個相似,弄明白上面的就不成問題。