OpenSSL中AES加密的用法
阿新 • • 發佈:2019-02-14
使用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.結尾
其他加密函式我還沒有用過,在此就不繼續列舉了,但是引數跟上面幾個相似,弄明白上面的就不成問題。