EVP主要封裝了以下功能:
1)已實現BASE64編解碼BIO;
2)實現生物信息的加密和解密;;
3)實現抽象生物;;
4)實現了可靠的io;
5)封裝摘要算法;
6)封裝對稱加解密算法;
7)封裝了非對稱密鑰的加密(公鑰)、解密(私鑰)、簽名和驗證以及輔助功能;
8)基於密碼的加密(PBE);
9)對稱密鑰處理;
10)數字信封:數字信封使用對方的公鑰加密對稱密鑰,用這個對稱密鑰加密數據。發送給對方時,對稱密鑰密文和數據密文同時發送。接收方首先用自己的私鑰解密密鑰密文以獲得對稱密鑰,然後用它解密數據。
11)其他輔助功能。
本文假設您已經安裝了OpenSSL,並且擁有1.1.1的源代碼副本。
EVP相關的頭文件在evp.h,源文件在crypto/evp目錄。
因為EVP的功能太強大了,而我的精力和水平有限,所以暫時只摘錄和說明部分功能。
這個結構定義了摘要算法的抽象方法。主要字段含義:
抽象算法的類型NID。
PKEY _ TYPE-與摘要算法相關的鍵NID。
MD _ size-匯總值的輸出大小。
旗幟-內部標誌。
init-初始化函數。
更新-進入計算功能。
最終輸出計算功能。
復制-匯總操作上下文復制功能。
清理-匯總操作上下文清理功能。
block _ size-匯總操作分組大小。
CTX大小-匯總操作數據包緩沖區大小。
MD _ CTRL-匯總操作指令控制功能。
支持的總結算法包括:
const EVP _ MD * EVP _ MD5(void);
const EVP _ MD * EVP _ sha 1(void);
const EVP _ MD * EVP _ sha 256(void);
const EVP _ MD * EVP _ sha 512(void);
以EVP_md5()為例,返回值為:
以下函數查詢md的屬性信息:
有時候我們不熟悉使用的總結算法,這些函數很有幫助。
EVP _ MD _ CTX * EVP _ MD _ CTX _新(void);
void EVP _ MD _ CTX _ free(EVP _ MD _ CTX * CTX);
這兩個函數用於創建和釋放對稱摘要上下文對象。
int EVP _ DigestInit(EVP _ MD _ CTX * CTX,const EVP _ MD * type);
抽象上下文被初始化,type是抽象算法的抽象集合。
1返回成功,0返回失敗。
int EVP _ digest update(EVP _ MD _ CTX * CTX,const void *d,size _ t CNT);
在總結中計算的海綿結構中輸入壹條數據。
1返回成功,0返回失敗。
int EVP _ digest final(EVP _ MD _ CTX * CTX,unsigned char *md,unsigned int * s);
生成最終摘要,並輸出摘要值和長度。
1返回成功,0返回失敗。
int EVP_Digest(const void *data,size_t count,unsigned char *md,unsigned int *size,const EVP_MD *type,ENGINE * impl);
用打包的壹次性方法計算壹小段數據的匯總。
1返回成功,0返回失敗。
結構evp_cipher_st {
int nid
int block _ size
/*可變長度密碼的默認值/
int key _ len
int iv _ len
/各種標誌/
無符號長標誌;
/ init鍵/
int ( init) (EVP_CIPHER_CTX *ctx,const無符號char *key,
const無符號char iv,int enc);
/加密/解密數據/
int(do _ CIPHER)(EVP _ CIPHER _ CTX * CTX,無符號char *out,
const無符號char in,size _ t inl);
/ cleanup ctx /
int(clean up)(EVP _ CIPHER _ CTX);
/多大的CTX-& gt;cipher_data需要是/
int ctx _ size
/用參數/填充ASN1_TYPE
int(set _ ASN 1 _ parameters)(EVP _ CIPHER _ CTX *,ASN 1 _ TYPE);
/從ASN1_TYPE /獲取參數
int(get _ ASN 1 _ parameters)(EVP _ CIPHER _ CTX *,ASN 1 _ TYPE);
/雜項操作/
int ( ctrl) (EVP_CIPHER_CTX *,int type,int arg,void ptr);
/應用程序數據*/
void app _ data
}/EVP _ CIPHER */;
typedef struct EVP _ CIPHER _ ST EVP _ CIPHER;
這個結構定義了對稱加密算法的抽象方法。主要字段含義:
加密算法的NID-NID。
block _ size-數據包大小。
key _ len-密鑰長度。
iv _ len-初始向量長度。
旗幟-內部標誌。
init-初始化函數。
do _ cipher-中間運算函數。
清理-最後的操作功能。
CTX大小-上下文大小。
ctrl-控制功能。
app _ data-應用數據。
支持的密碼抽象加密和解密算法包括:
const EVP _ CIPHER * EVP _ des _ ECB(void);
const EVP _ CIPHER * EVP _ des _ ede 3(void);
const EVP _ CIPHER * EVP _ AES _ 128 _ ECB(void);
const EVP _ CIPHER * EVP _ AES _ 128 _ CBC(void);
以下函數查詢密碼的屬性信息:
int EVP _ CIPHER _ NID(const EVP _ CIPHER * CIPHER);
int EVP _ CIPHER _ type(const EVP _ CIPHER * CTX);
#定義EVP _ CIPHER _ name(e)OBJ _ nid2sn(EVP _ CIPHER _ NID(e))
int EVP _ CIPHER _ block _ size(const EVP _ CIPHER * CIPHER);
int EVP_CIPHER_key_length(常量EVP _ CIPHER * CIPHER);
int EVP _ CIPHER _ iv _ length(const EVP _ CIPHER * CIPHER);
有時候我們不熟悉使用的加密算法,這些函數很有幫助。
EVP _ CIPHER _ CTX * EVP _ CIPHER _ CTX _ new(void);
void EVP _ CIPHER _ CTX _ free(EVP _ CIPHER _ CTX * c);
這兩個函數用於創建和釋放對稱加密和解密上下文對象。
int EVP _ CIPHER _ CTX _ set _ key _ length(EVP _ CIPHER _ CTX * x,int key len);
當對稱算法的密鑰長度可變時,設置對稱算法的密鑰長度。
1返回成功,0返回失敗。
int EVP _ CIPHER _ CTX _ set _ padding(EVP _ CIPHER _ CTX * c,int pad);
設置對稱算法的填充,有時會涉及到填充。
Pad取值為0和1,當pad為1時,使用填充。默認的填充策略采用PKCS5規範,即最後壹個包填充n個字節時,其填充值均為n。
1返回成功,0返回失敗。
int EVP _ encrypt init(EVP _ CIPHER _ CTX * CTX,const EVP_CIPHER *cipher,const unsigned char *key,const unsigned char * iv);
初始化對稱加密上下文。
添加1成功,失敗返回0。
int EVP _ encrypt update(EVP _ CIPHER _ CTX * CTX,unsigned char *out,int *outl,const unsigned char *in,int inl);
加密明文。
添加1成功,失敗返回0。成功時,outl輸出密文長度。
int EVP _ encrypt final(EVP _ CIPHER _ CTX * CTX,unsigned char *out,int * outl);
加密其余的明文。
添加1成功,失敗返回0。成功時,outl輸出密文長度。
int EVP _ decrypt init(EVP _ CIPHER _ CTX * CTX,const EVP_CIPHER *cipher,const unsigned char *key,const unsigned char * iv);
初始化對稱解密上下文。
添加1成功,失敗返回0。
int EVP _ decrypt update(EVP _ CIPHER _ CTX * CTX,unsigned char *out,int *outl,const unsigned char *in,int inl);
解密密文。
添加1成功,失敗返回0。如果成功,outl輸出明文長度。
int EVP _ decrypt final(EVP _ CIPHER _ CTX * CTX,unsigned char *outm,int * outl);
解密剩余的密文。
添加1成功,失敗返回0。如果成功,outl輸出明文長度。
int EVP _ BytesToKey(const EVP _ CIPHER * type,const EVP_MD *md,
const無符號char *salt,
const無符號char *data,int datal,int count
unsigned char *key,unsigned char * iv);
計算key函數,該函數根據算法類型、抽象算法、salt和輸入數據計算壹個對稱密鑰和初始化向量iv。追加鍵的長度。
該函數在PEM_do_header()函數中使用,根據密碼生成密鑰。
該結構定義了非對稱密鑰信息的存儲容器。主要字段含義:
非對稱加密算法的類型NID。
save _ type-保存的PKEY類型。
PKEY-保存的PKEY指針,如RSA結構指針。
EVP _ PKEY * EVP _ PKEY _ new(void);
void EVP _ PKEY _ free(EVP _ PKEY * PKEY);
這兩個函數用於創建和釋放PKEY上下文對象。
int EVP _ PKEY _ assign(EVP _ PKEY * PKEY,int type,void * key);
為PKEY關聯指定算法類型的上下文結構。例如,RSA關聯的宏定義如下:
#定義EVP_SignInit(a,b) EVP_DigestInit(a,b)
#定義EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
int EVP _ sign final(EVP _ MD _ CTX * CTX,無符號char *md,無符號int *s,
EVP _ PKEY * PKEY);
簽名計算。從宏定義可以看出,抽象其實是先計算,再用RSA私鑰加密。
添加1成功,失敗返回0。
#定義EVP_VerifyInit(a,b) EVP_DigestInit(a,b)
#定義EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
int EVP _ verify final(EVP _ MD _ CTX * CTX,const unsigned char *sigbuf
unsigned int siglen,EVP _ PKEY * PKEY);
檢查並簽署計算結果。從宏定義可以看出,其實是先計算摘要,然後用RSA公鑰解密簽名,再與摘要進行比較。
添加1成功,失敗返回0。
以下示例演示了使用兩種MD5方法進行抽象計算的過程。
輸出:
EVP_DigestInit() ret:[1]
EVP _ digest update()ret:[1]
EVP_DigestFinal() ret:[1]
e 380 e 88 e 8d 09 ebf 8d 8659 a 15b 0 ea 70 b 5
EVP_Digest() ret:1
e 380 e 88 e 8d 09 ebf 8d 8659 a 15b 0 ea 70 b 5
下面的例子演示了使用DES加密和解密的過程。為了便於程序實現,使用std::string作為例外。
輸出:
EVP_EncryptInit() ret:[1]
EVP _ encrypt update()ret:[1]
魔鬼:[24]
EVP _ encrypt final()ret:[1]
nCipherLen:[8]
密碼大小:[32]
EVP_DecryptInit() ret:[1]
EVP _ decrypt update()ret:[1]
nTextLen:[24]
EVP _ decrypt final()ret:[1]
nTextLen:[2]
文本大小:[26]正文:[abcdefghijklmnopqrstuvwxyz]
以下示例演示了使用SHA1進行RSA簽名和簽名驗證計算的過程。
輸出:
RSA _ generate _ key _ ex()ret:[1]
EVP _ PKEY _ assign _ RSA()ret:[1]
EVP_SignInit() ret:[1]
EVP_SignUpdate() ret:[1]
EVP_SignFinal() ret:[1]
sha1 len:[64]
EVP_VerifyInit() ret:[1]
EVP _ verify update()ret:[1]
EVP_VerifyFinal() ret:[1]