这次的RSA测试也是基于openssl的说明和网上现有的例子,只是测试了基本的公钥加密,私钥解密以及公钥/私钥文件生成和读取的功能,因为我用RSA的主要目的是加密AES的密钥,所以加解密数据设置的很简单,直接在main里面初始化了。整个工程中用到的openssl接口不是很多,最后自己又简单的封装了一下,便于以后使用。
/*rsa.h*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include<string.h> #include <openssl/rsa.h> #include <openssl/pem.h> #ifndef DEBUG #define RSADEBUG 1 #endif RSA* openssl_rsa_keygen(char* publickey,char* privatekey); int openssl_rsa_publickey_encrypt(char* in, int len, char* out, RSA* rsa); int openssl_rsa_privatekey_decrypt(char* in, int len, char* out, RSA* rsa); RSA* openssl_rsa_read_publickey(char* pubfile); RSA* openssl_rsa_read_privatekey(char* prifile); |
/*rsa.c*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
#include "rsa.h" RSA* openssl_rsa_keygen(char* publickey,char* privatekey) { int ret; RSA *rsa=NULL; int bits=2048; BIGNUM *b=NULL; unsigned long e=RSA_F4; BIO *bp_public = NULL, *bp_private = NULL; char *pubkey,*prikey; b=BN_new(); ret=BN_set_word(b,e); rsa=RSA_new(); RSA_generate_key_ex(rsa, bits, b, NULL); pubkey=publickey; prikey=privatekey; if(pubkey==NULL || strcmp(pubkey,"")==0) { pubkey=(char*)calloc(16,1); strcat(pubkey,"private.pem"); } if(prikey==NULL || strcmp(prikey,"")==0) { prikey=(char*)calloc(16,1); strcat(prikey,"private.pem"); } bp_public = BIO_new_file(pubkey, "w+"); ret = PEM_write_bio_RSAPublicKey(bp_public, rsa); bp_private = BIO_new_file(prikey, "w+"); ret = PEM_write_bio_RSAPrivateKey(bp_private, rsa, NULL, NULL, 0, NULL, NULL); BIO_free(bp_public); BIO_free(bp_private); return rsa; } int openssl_rsa_publickey_encrypt(char* in, int len, char* out, RSA* rsa) { RSA_public_encrypt(len , (unsigned char *)in , (unsigned char *)out , rsa , RSA_PKCS1_PADDING ); return 0; } int openssl_rsa_privatekey_decrypt(char* in, int len, char* out, RSA* rsa) { RSA_private_decrypt( len , (unsigned char *)in , (unsigned char *)out , rsa , RSA_PKCS1_PADDING ); return 0; } RSA* openssl_rsa_read_publickey(char* pubfile) { BIO *bp_public = NULL; char *pubf=pubfile; if(pubf==NULL || strcmp(pubf,"")==0) { pubf=(char*)calloc(16,1); strcat(pubf,"public.pem"); } bp_public=BIO_new_file(pubf, "r"); if(bp_public==NULL) return NULL; else return PEM_read_bio_RSAPublicKey(bp_public,NULL,NULL,NULL); } RSA* openssl_rsa_read_privatekey(char* prifile) { BIO *bp_private = NULL; char *prif=prifile; if(prif==NULL || strcmp(prif,"")==0) { prif=(char*)calloc(16,1); strcat(prif,"private.pem"); } bp_private=BIO_new_file(prif, "r"); if(bp_private==NULL) return NULL; else return PEM_read_bio_RSAPrivateKey(bp_private,NULL,NULL,NULL); //pri_rsa = PEM_read_RSAPrivateKey(fp,NULL,NULL,NULL); } |
/*main.c*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
#include "rsa.h" #pragma comment(lib,"libeay32.lib") #pragma comment(lib,"ssleay32.lib") int main(int argc, char* argv[]) { int ret=0; RSA *rsa=NULL; char *publickey="public.pem"; char *privatekey="private.pem"; BIO *bp; char in[32]={'1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f'}; char out[1024]={0}; char *p; int len; rsa=openssl_rsa_keygen(publickey,privatekey); /**测试RSA密钥生成**/ if(rsa==NULL) { printf("rsa init failed\n"); return 0; } printf("RSA_public_encrypt/RSA_private_decrypt\n"); len=RSA_size(rsa); /** openssl是这样描述RSA_size()的: This function returns the RSA modulus size in bytes. It can be used to determine how much memory must be allocated for an RSA encrypted value. rsa->n must not be NULL. 还不太明白为什么加密后的数据大小一定要这么设置,测试增大申请的内容也可以加解密,但是主板蜂鸣器会响**/ p=(char*)calloc(len,1); openssl_rsa_publickey_encrypt(in ,sizeof(in), p , rsa ); //printf("rsa encrypted(%d):\n%s\n",len,p); openssl_rsa_privatekey_decrypt(p,len,out,rsa); /**解密的数据长度len要和加密是一致,否则解不出来数据**/ printf("rsa decrypted:\n%s\n",out); RSA_free( rsa ); free(p); printf("PEM_read_bio_RSAPublicKey/PEM_read_bio_RSAPrivateKey\n"); rsa=openssl_rsa_read_publickey(NULL); /**测试读取公钥初始化RSA**/ if(RSADEBUG){ RSA_print_fp(stdout,rsa,0);} /**打印RSA的密钥信息**/ len=RSA_size(rsa); p=(char*)calloc(len,1); openssl_rsa_publickey_encrypt(in ,sizeof(in), p , rsa ); RSA_free(rsa); rsa=openssl_rsa_read_privatekey(NULL); /**测试读取私钥初始化RSA*/ if(RSADEBUG){ RSA_print_fp(stdout,rsa,0);} memset(out,0,1024); openssl_rsa_privatekey_decrypt(p,len,out,rsa); printf("decrypted data:\n%s",out); return 0; } /** http://www.codepool.biz/tech-frontier/how-to-use-openssl-generate-rsa-keys-cc.html **/ |
后记:openssl内容很丰富,功能也很强大,里面提供了好多接口都很实用,但是相比较UNIX的各种系统接口函数,openssl的定义和和说明,我个人感觉实在是有些乱,不够整齐,当然了这只是一些吹毛求疵的要求,对于使用没有任何影响,反正整个openssl的源码都提供给你了,天才们的智慧结晶已经完美的展现在了算法中 ,要是想看着美观点,完全可以自己去改改