openssl命令列和API

dsfire發表於2020-06-02

當安裝openssl輕量版時(OpenSSL v1.1.1g Light),可以使用openssl命令進行演算法的驗證。若需要使用API進行演算法驗證,則需要安裝完整版,這兩個的下載路徑為:http://slproweb.com/products/Win32OpenSSL.html

AES-256 CBC模式 加鹽,使用pass加密檔案

命令列為:

加密為:openssl enc -aes-256-cbc -e -md md5 -in input.txt -out encrypted.txt -pass pass:hello -p

解密為:openssl enc -aes-256-cbc -d -md md5 -in encrypted.txt -out decrypted.txt -pass pass:hello -p

其中:

-e為加密,-d為解密。

-md為基於哪一種摘要演算法來產生key和iv,依據pass。也可採用key和iv指定而不用pass。hello為密碼。

-p列印key和iv。

預設加鹽,可以使用openssl enc --help來檢視選項

若不使用-md,openssl版本不同,預設使用的演算法是不一樣的,低版本有用md5,高版本有用sha256,因此需明確指定-md演算法。

API如下:

API有兩種模式,一個是基於AES的API,一個是基於EVP框架的API。

此處僅說明解密,加密基本類似。若加密時加鹽了,那需先獲取鹽值。salt值儲存在加密後檔案頭部,以Salted__開始,後續8個位元組即為鹽值。網址中https://blog.csdn.net/appletreesujie/article/details/17580401使用BIOread來進行鹽值讀取。讀取完鹽值之後需使用EVP_BytesToKey獲得key和iv。對應到上述解密命令,EVP API示意為:

key_len = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), salt_value, passwd, strlen(passwd), 1, key, iv); // 返回值為key的長度,salt_value為從加密檔案中獲取的鹽值,為8位元組,可以使用巨集PKCS5_SALT_LEN定義改陣列。針對aes256,key為32位元組,可以使用EVP_MAX_KEY_LENGTH定義該資料。iv為16位元組,可以使用EVP_MAX_IV_LENGTH定義該陣列。
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
ret = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv)
if(1 != ret)
{
    error();
}
ret = EVP_DecryptUpdate(&ctx, decrypted_buffer, &decrypted_out_len, &encrypted_buffer, encrypted_len); // encrypted_buffer需略去鹽值部分,encrypted_len也需略去鹽值部分
if(1 != ret)
{
    error();
}
out_len = decrypted_out_len;
ret = EVP_DecryptFInal_ex(&ctx, &decrypted_buffer[decrypted_out_len], &decrypted_out_len); // 填充的資料
if(1 != ret)
{
    error();
}
out_len += decrypted_out_len; // 解密的資料長度,解密資料都在decryped_buffer中。

EVP_CIPHER_CTX_cleanup(&ctx); // free對應new

在實際使用中,encrypted_buffer和decrypted_buffer不可能申請那麼大,每次使用可能只能讀取一小部分資料,可參考:https://my.oschina.net/u/2539854/blog/1559531來進行迴圈解密。特別注意的一點是:申請的out_buffer需比in_buffer大EVP_MAX_BLOCK_LENGTH位元組。

aes api可參考https://blog.csdn.net/yexiangcsdn/article/details/79220722

HMAC

aes加密可以將明文變成密文,但解密後資料是否完整不能保證。HMAC演算法是一種基於金鑰的報文完整性的驗證方法。HMAC運算利用hash演算法,以一個訊息M和一個金鑰K作為輸入,生成一個定長的訊息摘要作為輸出。HMAC演算法利用已有的Hash函式。簡單來說,HMAC使用來產生摘要資訊的,跟一個檔案的md5值類似,不過HMAC不僅需要訊息M,還需要一個key。參考:https://blog.csdn.net/Aqu415/article/details/102792623

命令列:

openssl dgst -hmac hello -sha256 input.txt

其中:

-sha256使用hash256來產生摘要資訊,可選擇其它

hello為密碼,HMAC的金鑰長度可以是任意大小,如果小於n(hash輸出值的大小),那麼將會消弱演算法安全的強度

API模式:

HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, key, strlen(key), EVP_sha256(), NULL);
HMAC_Update(&ctx, input_buffer, in_len);
HMAC_Final(&ctx, md_value, &len); // md_value為md陣列,可定義為EVP_MAX_MD_SIZE
HMAC_CTX_cleanup(&ctx);
// 以上並沒有判斷返回值,實際中需判斷返回值

EVP框架:

EVP_MD_CTX * md_ctx;
md_ctx = EVP_MD_CTX_new();
EVP_PKEY * pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, passwd, strlen(passwd));
EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey);
EVP_DigestSignUpdate(md_ctx, input_bffer, len);
md_len = sizeof(md_buffer);
EVP_DigestSignFinal(md_ctx, md_buffer, &md_len); // md_buffer可申請EVP_MAX_MD_SIZE,md_len最後為實際長度值
// 上述均沒有判斷返回值,實際應用中需判斷返回值

同樣可以參考https://my.oschina.net/u/2539854/blog/1559531來進行迴圈解密。

若僅產生摘要,不需要key,可使用如下函式組合:

EVP_DigestInit_ex

EVP_DigestUpdate

EVP_DigestFinal_ex

相關文章