linux以下C 利用openssl的AES庫加密,解密


OpenSSL提供了AES加解密算法的API


const char *AES_options(void);

AES算法狀態,是所有支持或者是部分支持。

返回值:“aes(full)” 或者"aes(partial)"


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

設定加密用的Key;

userKey: 密鑰數值。

bits:密鑰長度,以bit為單位。假設密鑰數字是16個字節,則此參數值應為128。

key: AES_KEY對象指針;

返回值: 0 成功, -1 userkey,key為空, -2: 密鑰長度不是128。192。256;


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

設定解密用的Key;

userKey: 密鑰數值;

bits:密鑰長度,以bit為單位,假設密鑰數字是16個字節。則此參數值應為128;

key: AES_KEY對象指針;

返回值: 0 成功, -1 userkey。key為空。 -2: 密鑰長度不是128。192,256。


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

AES 加密。加密單個數據塊。in,out能夠是同一內存區;

in: 須要加密的數據;

out: 加密后的數據。

key:AES 密鑰。


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

AES 解密。解密單個數據塊,in。out能夠是同一內存區;

in: 須要解密的數據。

out: 解密后的數據;

key:AES 密鑰。


void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,    const AES_KEY *key, const int enc);

AES加密/解密單個數據塊,ECB模式

in: 須要加密/解密的數據;

out: 計算后輸出的數據。

key:密鑰

enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密。


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

AES加密/解密單個數據塊,CBC模式

in: 須要加密/解密的數據;

out: 計算后輸出的數據。

length: 數據長度

key:密鑰

ivec: 初始向量

enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密;


void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char *ivec, int *num, const int enc);
AES CFB128位模式加密/解密。輸入輸出數據區能夠重疊。
in: 須要加密/解密的數據。
out: 計算后輸出的數據;
length: 數據長度;
key: 密鑰;
ivec: 初始化向量
num: 輸出參數。計算狀態。多少個CFB數據塊
enc: 計算模式。 加密: AES_ENCRYPT 。 解密: AES_DECRYPT
    
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char *ivec, int *num, const int enc);
AES CFB1位模式加密/解密。輸入輸出數據區能夠重疊;
in: 須要加密/解密的數據;
out: 計算后輸出的數據;
length: 數據長度;
key: 密鑰;
ivec: 初始化向量
num: 輸出參數,計算狀態,多少個CFB數據塊
enc: 計算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT
    
    
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char *ivec, int *num, const int enc);
AES CFB8位模式加密/解密。輸入輸出數據區能夠重疊;
in: 須要加密/解密的數據;
out: 計算后輸出的數據;
length: 數據長度;
key: 密鑰;
ivec: 初始化向量
num: 輸出參數,計算狀態,多少個CFB數據塊
enc: 計算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT

    
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char *ivec, int *num);
AES OFB128位模式加密/解密,輸入輸出數據區能夠重疊;
in: 須要加密/解密的數據;
out: 計算后輸出的數據。
length: 數據長度;
key: 密鑰。
ivec: 初始化向量
num: 輸出參數,計算狀態,多少個CFB數據塊
enc: 計算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT

        
    
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
    size_t length, const AES_KEY *key,
    unsigned char ivec[AES_BLOCK_SIZE],
    unsigned char ecount_buf[AES_BLOCK_SIZE],
    unsigned int *num);
AES CTR128位模式加密/解密,輸入輸出數據區能夠重疊;
in: 須要加密/解密的數據。
out: 計算后輸出的數據;
length: 數據長度;
key: 密鑰。
ivec: 初始化向量
ecount_buf: 輸出參加,加密的次數,在第一次調用此函數時,須要初始化為0
num: 輸出參數,計算狀態,多少個CFB數據塊,在第一次調用此函數時,須要初始化為0
enc: 計算模式。 加密: AES_ENCRYPT , 解密: AES_DECRYPT



void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
             size_t length, const AES_KEY *key,
             unsigned char *ivec, const int enc);
AES 加密/解密,輸入輸出數據區能夠重疊,初始化向量是加密數據塊的2倍,加密前用前半部分做一次異或。加密后用后半部分做一次異或;
in: 須要加密/解密的數據;
out: 計算后輸出的數據。
length: 數據長度;
key: 密鑰;
ivec: 初始化向量
enc: 計算模式。 加密: AES_ENCRYPT , 解密: AES_DECRYPT
    
                 

void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
            size_t length, const AES_KEY *key,
            const AES_KEY *key2, const unsigned char *ivec,
            const int enc);
AES 加密/解密。輸入輸出數據區能夠重疊。初始化向量是加密數據塊的4倍,加密前用第一部分做一次異或。加密后用第二部分做一次異或;
最后一個加密數據塊,加密前用第三部分異或,加密后用第四部分異或;
in: 須要加密/解密的數據;
out: 計算后輸出的數據;
length: 數據長度。
key: 密鑰。
ivec: 初始化向量
enc: 計算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT            

int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
        unsigned char *out,
        const unsigned char *in, unsigned int inlen)

用AES算法對明文key數據加密

key: AES Key,用於加密密鑰數據

iv: 初始化向量

out: 加密后的密鑰數據

in: 密鑰數據

inlen: 密鑰數據長度

返回值: 1: 成功。 0: 失敗


int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
        unsigned char *out,
        const unsigned char *in, unsigned int inlen)

用AES算法對明文key數據加密

key: AES Key,用於加密密鑰數據

iv: 初始化向量

out: 加密后的密鑰數據

in: 密鑰數據

inlen: 密鑰數據長度

返回值: 1: 成功, 0: 失敗


C實例分析:

首先要了解AES加密是什么。以及幾種加密模式的差別。之后才是編程。

詳細的編程案例,在以下的鏈接。

openssl之aes加密(AES_cbc_encrypt 與 AES_encrypt 的編程案例)

以下這個鏈接有具體圖解。
http://www.cnblogs.com/adylee/archive/2007/09/14/893438.html
ECB模式 
  長處: 
  1.簡單; 
  2.有利於並行計算。 
  3.誤差不會被傳送。 
  缺點: 
  1.不能隱藏明文的模式; 
  2.可能對明文進行主動攻擊; 
CBC模式: 
  長處: 
  1.不easy主動攻擊,安全性好於ECB,適合傳輸長度長的報文,是SSL、IPSec的標准。 
  缺點: 
  1.不利於並行計算。 
  2.誤差傳遞。 
  3. 須要初始化向量IV 
CFB模式: 
  長處: 
  1.隱藏了明文模式; 
  2.分組password轉化為流模式; 
  3.能夠及時加密傳送小於分組的數據; 
  缺點: 
  1.不利於並行計算; 
  2.誤差傳送:一個明文單元損壞影響多個單元; 
  3.唯一的IV; 
ofb模式: 
  長處: 
  1.隱藏了明文模式; 
  2.分組password轉化為流模式; 
  3.能夠及時加密傳送小於分組的數據; 
  缺點: 
  1.不利於並行計算; 
  2.對明文的主動攻擊是可能的; 
  3.誤差傳送:一個明文單元損壞影響多個單元; 


了解這些加密模式之后,再看openssl提供的接口就好理解了。

下面接口來自“crypto/aes/aes.h”。有openssl源代碼。
//設置加密和解密器
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);

//默認的加密解密方式,參數好理解
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);

//以下這些也是經常使用的加密方式,可是參數非常多,而源代碼對於參數使用介紹不多。僅僅能摸索
void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key, const int enc);
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc); //參數相對復雜
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num);
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num);

從以下這個文件能夠看出, AES_encrypt 就是ecb加密的方式。而AES_set_encrypt_key和 AES_encrypt,它們的實如今"crypto/aes/aes_x86core.c"和 "crypto/aes/aes_core.c",也就是有兩個版本號,依據平台選擇。

看源代碼。

調用實例:
[cpp]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. int aes_encrypt(char* in, char* key, char* out)//, int olen)  
  2. {  
  3.     if(!in || !key || !out) return 0;  
  4.     AES_KEY aes;  
  5.     if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)  
  6.     {  
  7.         return 0;  
  8.     }  
  9.     int len=strlen(in), en_len=0;  
  10.     while(en_len<len)//輸入輸出字符串夠長。而且是AES_BLOCK_SIZE的整數倍,須要嚴格限制  
  11.     {  
  12.         AES_encrypt((unsigned char*)in, (unsigned char*)out, &aes);  
  13.         in+=AES_BLOCK_SIZE;  
  14.         out+=AES_BLOCK_SIZE;  
  15.         en_len+=AES_BLOCK_SIZE;  
  16.     }  
  17.     return 1;  
  18. }  
  19. int aes_decrypt(char* in, char* key, char* out)  
  20. {  
  21.     if(!in || !key || !out) return 0;  
  22.     AES_KEY aes;  
  23.     if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)  
  24.     {  
  25.         return 0;  
  26.     }  
  27.     int len=strlen(in), en_len=0;  
  28.     while(en_len<len)  
  29.     {  
  30.         AES_decrypt((unsigned char*)in, (unsigned char*)out, &aes);  
  31.         in+=AES_BLOCK_SIZE;  
  32.         out+=AES_BLOCK_SIZE;  
  33.         en_len+=AES_BLOCK_SIZE;  
  34.     }  
  35.     return 1;  
  36. }  


最后給出一個鏈接,利用openssl的AES接口進行編程。

參考資料:

分組對稱加密模式:ECB/CBC/CFB/OFB缺CTR

http://fossies.org/dox/openssl-1.0.1f/index.html  (具體源代碼)


命令行下openssl對文件加密解密:

--建立文件test.txt, 特意寫入中英文

# cd /tmp

# echo "test測試" > test.txt

--開始加密, 使用aes-128-cbc算法, 也能夠使用其它算法, 通過查看openssl的幫助可獲知

# openssl aes-128-cbc -salt -in test.txt -out test.txt.aes
enter aes-128-cbc encryption password:<輸入密碼>
Verifying - enter aes-128-cbc encryption password:<確認密碼>

--查看加密前后的文件大小, 加密后文件明顯增大了

# ll test.txt*  
-rw-r--r--  1 root root  9 Aug 11 15:42 test.txt
-rw-r--r--  1 root root 32 Aug 11 15:43 test.txt.aes

--查看加密前后的文件內容, 加密后文件無法直接查看, 顯示亂碼

# cat test.txt
test測試

# cat test.txt.aes
Salted__碾RTqm6棚顱

--如今開始解密, 會提示輸入password, 假設password有誤則無法解密

# openssl aes-128-cbc -d -salt -in test.txt.aes -out test.txt.out
enter aes-128-cbc decryption password:<輸入錯誤密碼>
bad decrypt
6150:error:06065064:digital envelope routines:EVP_DecryptFinal:bad decrypt:evp_enc.c:438:

# openssl aes-128-cbc -d -salt -in test.txt.aes -out test.txt.out
enter aes-128-cbc decryption password:<輸入正確密碼>

--查看解密前后的文件大小, 和加密前是一樣的

# ll test.txt*
-rw-r--r--  1 root root  9 Aug 11 15:42 test.txt
-rw-r--r--  1 root root 32 Aug 11 15:43 test.txt.aes
-rw-r--r--  1 root root  9 Aug 11 15:45 test.txt.out

--查看解密前后的文件內容, 和加密前是一樣的

# cat test.txt.out
test測試

這樣的方法很適合Linux下的文件內容保密, 呵呵....以上命令加參數比較復雜, 我們能夠把命令加參數做個函數, 然后放到.bash_profile里, 這樣每次登陸后直接使用函數就可以, 例如以下:


function jiami() 

 /usr/bin/openssl aes-128-cbc -salt -in $1 -out $1.aes && rm -f $1

}

function jiemi() 

 /usr/bin/openssl aes-128-cbc -d -salt -in $1.aes -out $1 && rm -f $1.aes

}


然后就能夠例如以下使用了(注意輸入參數都是原文件名稱, 且會自己主動刪除原文件):

# jiami test.txt
enter aes-128-cbc encryption password:
Verifying - enter aes-128-cbc encryption password:

# jiemi test.txt
enter aes-128-cbc decryption password:

# ll test.txt*  
-rw-r--r--  1 root root 9 Aug 11 15:46 test.txt
-rw-r--r--  1 root root 9 Aug 11 15:45 test.txt.out

--End--


免責聲明!

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



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