最近工作需要使用一些加密算法。之前嘗試過cryptopp以及polarssl,聽說openssl中的加密模塊特別全,並且特別好用。於是想嘗試一下。
一、環境配置
下載openssl,我這里使用的是openssl-1.0.1s。解壓后查看自帶的win32說明文件。我這里解壓到d盤
按照安裝說明下載activeperl。
二、編譯靜態庫
執行命令:
cd D:\openssl-1.0.1s D: perl Configure VC-WIN32 no-asm --prefix=D:\openssl-1.0.1s ms\do_ms
有類似輸出
然后打開vs2010命令行工具
cd d:\openssl-1.0.1s d: nmake -f ms\nt.mak
等待幾分鍾,完成后在\out32目錄下有靜態庫文件。
說明:
1.若想生成dll 則將ms\nt.mak 改為ms\ntdll.mak
2.默認情況下,靜態庫使用的是MT,動態庫使用的是MD
3.若想指定MT或MD,修改nt.mak或ntdll.mak 對應CFLAG=內容。
4.若想生成Debug版本的靜態庫,perl選項設置中修改VC-WIN32為debug-VC-WIN32
三、使用靜態庫
新建控制台項目
切換Debug生成選項為release
在項目--屬性--VC++目錄包含目錄添加
D:\openssl-1.0.1s\inc32
庫目錄添加
D:\openssl-1.0.1s\out32;
在項目--屬性--C++--連接器--代碼生成中修改MD為MT
測試RSA加密解密代碼如下:
// testOpenssl.cpp : 定義控制台應用程序的入口點。 // #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/bio.h> #include <fstream> #pragma comment(lib, "libeay32.lib") #pragma comment(lib, "ssleay32.lib") // 生成公鑰文件和私鑰文件,私鑰文件帶密碼 int generate_key_files(const char *pub_keyfile, const char *pri_keyfile, const unsigned char *passwd, int passwd_len) { RSA *rsa = NULL; rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL); if(rsa == NULL) { printf("RSA_generate_key error!\n"); return -1; } // 開始生成公鑰文件 BIO *bp = BIO_new(BIO_s_file()); if(NULL == bp) { printf("generate_key bio file new error!\n"); return -1; } if(BIO_write_filename(bp, (void *)pub_keyfile) <= 0) { printf("BIO_write_filename error!\n"); return -1; } if(PEM_write_bio_RSAPublicKey(bp, rsa) != 1) { printf("PEM_write_bio_RSAPublicKey error!\n"); return -1; } // 公鑰文件生成成功,釋放資源 printf("Create public key ok!\n"); BIO_free_all(bp); // 生成私鑰文件 bp = BIO_new_file(pri_keyfile, "w+"); if(NULL == bp) { printf("generate_key bio file new error2!\n"); return -1; } if(PEM_write_bio_RSAPrivateKey(bp, rsa, EVP_des_ede3_ofb(), (unsigned char *)passwd, passwd_len, NULL, NULL) != 1) { printf("PEM_write_bio_RSAPublicKey error!\n"); return -1; } // 釋放資源 printf("Create private key ok!\n"); BIO_free_all(bp); RSA_free(rsa); return 0; } // 打開公鑰文件,返回EVP_PKEY結構的指針 EVP_PKEY* open_public_key(const char *keyfile) { EVP_PKEY* key = NULL; RSA *rsa = NULL; OpenSSL_add_all_algorithms(); BIO *bp = BIO_new(BIO_s_file());; BIO_read_filename(bp, keyfile); if(NULL == bp) { printf("open_public_key bio file new error!\n"); return NULL; } rsa = PEM_read_bio_RSAPublicKey(bp, NULL, NULL, NULL); if(rsa == NULL) { printf("open_public_key failed to PEM_read_bio_RSAPublicKey!\n"); BIO_free(bp); RSA_free(rsa); return NULL; } printf("open_public_key success to PEM_read_bio_RSAPublicKey!\n"); key = EVP_PKEY_new(); if(NULL == key) { printf("open_public_key EVP_PKEY_new failed\n"); RSA_free(rsa); return NULL; } EVP_PKEY_assign_RSA(key, rsa); return key; } // 打開私鑰文件,返回EVP_PKEY結構的指針 EVP_PKEY* open_private_key(const char *keyfile, const unsigned char *passwd) { EVP_PKEY* key = NULL; RSA *rsa = RSA_new(); OpenSSL_add_all_algorithms(); BIO *bp = NULL; bp = BIO_new_file(keyfile, "rb"); if(NULL == bp) { printf("open_private_key bio file new error!\n"); return NULL; } rsa = PEM_read_bio_RSAPrivateKey(bp, &rsa, NULL, (void *)passwd); if(rsa == NULL) { printf("open_private_key failed to PEM_read_bio_RSAPrivateKey!\n"); BIO_free(bp); RSA_free(rsa); return NULL; } printf("open_private_key success to PEM_read_bio_RSAPrivateKey!\n"); key = EVP_PKEY_new(); if(NULL == key) { printf("open_private_key EVP_PKEY_new failed\n"); RSA_free(rsa); return NULL; } EVP_PKEY_assign_RSA(key, rsa); return key; } // 使用密鑰加密,這種封裝格式只適用公鑰加密,私鑰解密,這里key必須是公鑰 int rsa_key_encrypt(EVP_PKEY *key, const unsigned char *orig_data, size_t orig_data_len, unsigned char *enc_data, size_t &enc_data_len) { EVP_PKEY_CTX *ctx = NULL; OpenSSL_add_all_ciphers(); ctx = EVP_PKEY_CTX_new(key, NULL); if(NULL == ctx) { printf("ras_pubkey_encryptfailed to open ctx.\n"); EVP_PKEY_free(key); return -1; } if(EVP_PKEY_encrypt_init(ctx) <= 0) { printf("ras_pubkey_encryptfailed to EVP_PKEY_encrypt_init.\n"); EVP_PKEY_free(key); return -1; } if(EVP_PKEY_encrypt(ctx, enc_data, &enc_data_len, orig_data, orig_data_len) <= 0) { printf("ras_pubkey_encryptfailed to EVP_PKEY_encrypt.\n"); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); return -1; } EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); return 0; } // 使用密鑰解密,這種封裝格式只適用公鑰加密,私鑰解密,這里key必須是私鑰 int rsa_key_decrypt(EVP_PKEY *key, const unsigned char *enc_data, size_t enc_data_len, unsigned char *orig_data, size_t &orig_data_len, const unsigned char *passwd) { EVP_PKEY_CTX *ctx = NULL; OpenSSL_add_all_ciphers(); ctx = EVP_PKEY_CTX_new(key, NULL); if(NULL == ctx) { printf("ras_prikey_decryptfailed to open ctx.\n"); EVP_PKEY_free(key); return -1; } if(EVP_PKEY_decrypt_init(ctx) <= 0) { printf("ras_prikey_decryptfailed to EVP_PKEY_decrypt_init.\n"); EVP_PKEY_free(key); return -1; } if(EVP_PKEY_decrypt(ctx, orig_data, &orig_data_len, enc_data, enc_data_len) <= 0) { printf("ras_prikey_decryptfailed to EVP_PKEY_decrypt.\n"); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); return -1; } EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); return 0; } int main() { char enc_text[512] = ""; char dec_text[512] = ""; size_t enc_len = 512; size_t dec_len = 512; //生成密鑰對 generate_key_files("public.pem","private.pem",(const unsigned char*)"1234",4); EVP_PKEY* pubkey = open_public_key("public.pem"); EVP_PKEY* prikey = open_private_key("private.pem",(const unsigned char *)"1234"); rsa_key_encrypt(pubkey,(const unsigned char*)"hello",6,(unsigned char*)enc_text,enc_len); rsa_key_decrypt(prikey,(const unsigned char*)enc_text,enc_len,(unsigned char*)dec_text,dec_len,(const unsigned char *)"1234"); printf("%s\n",dec_text); return 0; }