當前位置:編程學習大全網 - 源碼下載 - OpenSSL之EVP用法

OpenSSL之EVP用法

OpenSSL EVP(high-level cryptographic functions)提供了豐富的密碼學中的各種函數。OpenSSL中實現了各種對稱算法、摘要算法以及簽名/驗簽算法。EVP函數將這些具體的算法進行了封裝。

EVP主要封裝了如下功能函數:

1)實現了BASE64編解碼BIO;

2)實現了加解密BIO;

3)實現了摘要BIO;

4)實現了reliable BIO;

5)封裝了摘要算法;

6)封裝了對稱加解密算法;

7)封裝了非對稱密鑰的加密(公鑰)、解密(私鑰)、簽名與驗證以及輔助函數;

8)基於口令的加密(PBE);

9)對稱密鑰處理;

10)數字信封:數字信封用對方的公鑰加密對稱密鑰,數據則用此對稱密鑰加密。發送給對方時,同時發送對稱密鑰密文和數據密文。接收方首先用自己的私鑰解密密鑰密文,得到對稱密鑰,然後用它解密數據。

11)其他輔助函數。

本文假設妳已經安裝好了OpenSSL,並且持有壹份1.1.1的源碼。

EVP相關的頭文件在evp.h中、源文件在crypto/evp目錄中。

由於EVP的功能過於強大,再加上我的精力和水平有限,暫時只對部分功能進行摘錄和說明。

這個結構定義了摘要算法的抽象方法。主要字段含義:

type —— 摘要算法的NID。

pkey_type —— 與摘要算法相關的密鑰NID。

md_size —— 摘要值的輸出大小。

flags —— 內部標誌。

init —— 初使化函數。

update —— 輸入計算函數。

final —— 輸出計算函數。

copy —— 摘要運算上下文復制函數。

cleanup —— 摘要運算上下文清理函數。

block_size —— 摘要運算分組大小。

ctx_size —— 摘要運算分組緩沖區大小。

md_ctrl —— 摘要運算指令控制函數。

支持的摘要算法包括:

const EVP_MD *EVP_md5(void);

const EVP_MD *EVP_sha1(void);

const EVP_MD *EVP_sha256(void);

const EVP_MD *EVP_sha512(void);

拿EVP_md5()來說,其返回值為:

下面這幾個函數查詢md的屬性信息:

有時我們對使用的摘要算法不熟悉,這幾個函數很有幫助。

EVP_MD_CTX *EVP_MD_CTX_new(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_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);

向摘要計算的海棉結構輸入壹段數據。

成功返回1,失敗返回0。

int EVP_DigestFinal(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。

struct evp_cipher_st {

int nid;

int block_size;

/* Default value for variable length ciphers /

int key_len;

int iv_len;

/ Various flags /

unsigned long flags;

/ init key /

int ( init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,

const unsigned char iv, int enc);

/ encrypt/decrypt data /

int ( do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,

const unsigned char in, size_t inl);

/ cleanup ctx /

int ( cleanup) (EVP_CIPHER_CTX );

/ how big ctx->cipher_data needs to be /

int ctx_size;

/ Populate a ASN1_TYPE with parameters /

int ( set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE );

/ Get parameters from a ASN1_TYPE /

int ( get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE );

/ Miscellaneous operations /

int ( ctrl) (EVP_CIPHER_CTX *, int type, int arg, void ptr);

/ Application data */

void app_data;

} / EVP_CIPHER */ ;

typedef struct evp_cipher_st EVP_CIPHER;

這個結構定義了對稱加密算法的抽象方法。主要字段含義:

nid —— 加密算法的NID。

block_size —— 分組大小。

key_len —— 密鑰長度。

iv_len —— 初使向量長度。

flags —— 內部標誌。

init —— 初使化函數。

do_cipher —— 中間運算函數。

cleanup —— 最終運算函數。

ctx_size —— 上下文大小。

ctrl —— 控制函數。

app_data —— 應用程序數據。

支持的CIPHER抽象加解密算法包括:

const EVP_CIPHER *EVP_des_ecb(void);

const EVP_CIPHER *EVP_des_ede3(void);

const EVP_CIPHER *EVP_aes_128_ecb(void);

const EVP_CIPHER *EVP_aes_128_cbc(void);

下面這幾個函數查詢cipher的屬性信息:

int EVP_CIPHER_nid(const EVP_CIPHER *cipher);

int EVP_CIPHER_type(const EVP_CIPHER *ctx);

# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))

int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);

int EVP_CIPHER_key_length(const 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 keylen);

當對稱算法密鑰長度為可變長時,設置對稱算法的密鑰長度。

成功返回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_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv);

初使化對稱加密上下文。

成功返加1,失敗返回0。

int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);

加密壹段明文。

成功返加1,失敗返回0。成功時,outl輸出密文長度。

int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);

加密余下的明文。

成功返加1,失敗返回0。成功時,outl輸出密文長度。

int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv);

初使化對稱解密上下文。

成功返加1,失敗返回0。

int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);

解密壹段密文。

成功返加1,失敗返回0。成功時,outl輸出明文長度。

int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);

解密余下的密文。

成功返加1,失敗返回0。成功時,outl輸出明文長度。

int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,

const unsigned char *salt,

const unsigned char *data, int datal, int count,

unsigned char *key, unsigned char *iv);

計算密鑰函數,它根據算法類型、摘要算法、salt以及輸入數據計算出壹個對稱密鑰和初始化向量iv。返加密鑰的長度。

在PEM_do_header()函數中根據口令生成密鑰時,有使用到這個函數。

這個結構定義了非對稱密鑰信息的存儲容器。主要字段含義:

type —— 非對稱加密算法的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關聯的宏定義如下:

# define EVP_SignInit(a,b) EVP_DigestInit(a,b)

# define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c)

int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s,

EVP_PKEY *pkey);

簽名計算。從宏定義可以看出實際上就是先計算摘要,再用RSA私鑰加密。

成功返加1,失敗返回0。

# define EVP_VerifyInit(a,b) EVP_DigestInit(a,b)

# define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c)

int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,

unsigned int siglen, EVP_PKEY *pkey);

驗簽計算。從宏定義可以看出實際上就是先計算摘要,再用RSA公鑰解密簽名,再與摘要進行比對。

成功返加1,失敗返回0。

下面這個例子演示了使用MD5的兩種方法進行摘要計算的過程。

輸出:

EVP_DigestInit() ret:[1]

EVP_DigestUpdate() ret:[1]

EVP_DigestFinal() ret:[1]

e380e88e8d09ebf8d8659a15b0ea70b5

EVP_Digest() ret:1

e380e88e8d09ebf8d8659a15b0ea70b5

下面這個例子演示了使用DES進行加解密的過程。為了方便程序實現,破例使用了std::string。

輸出:

EVP_EncryptInit() ret:[1]

EVP_EncryptUpdate() ret:[1]

nCipherLen:[24]

EVP_EncryptFinal() ret:[1]

nCipherLen:[8]

cipher size:[32]

EVP_DecryptInit() ret:[1]

EVP_DecryptUpdate() ret:[1]

nTextLen:[24]

EVP_DecryptFinal() ret:[1]

nTextLen:[2]

text size:[26] body:[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_VerifyUpdate() ret:[1]

EVP_VerifyFinal() ret:[1]

  • 上一篇:國外舞曲網站(國外舞曲排行榜前十名)
  • 下一篇:微信第三方軟件有哪些?
  • copyright 2024編程學習大全網