OpenSSL库的RSA使用(上)-EVP方式
来源:互联网 发布:化妆品网络供货平台 编辑:程序博客网 时间:2024/05/29 10:55
1 RSA加解密方式介绍
使用OpenSSL的RSA方式加解密有两种方式,一种是使用EVP系列函数,这些函数提供了对底层加解密函数的封装;另外一种是直接使用RSA相关的函数进行加解密操作。如果是标准应用,如使用RSA公钥加密,私钥解密,使用EVP函数比较方便,如果有特殊应用,如私钥加密,公钥解密,EVP函数会有问题,可以直接使用RSA提供的函数。
不过OpenSSL的RSA库经过测试,发现也有些问题,最后会对这些问题进行整理总结。
注:关于OpenSSL RSA是谁,有啥本事,去哪能找到它,请自行找度娘或谷歌。
1 EVP函数方式
1.1 步骤
使用EVP函数方式加解密的一般步骤是:
i. 生成公钥和私钥文件(公钥文件和私钥文件都是文本)
ii. 打开公钥,使用公钥对源数据进行加密
iii. 打开私钥,使用私钥对密文进行解密
1.2 代码
1.2.1包含文件与宏定义
#include <stdio.h>#include <openssl/evp.h>#include <crypto/evp/evp_locl.h>#include <openssl/rand.h>#include <openssl/rsa.h>#include <openssl/pem.h>#define RSA_KEY_LENGTH 1024static const char rnd_seed[] = "string to make the random number generator initialized";#ifdef WIN32#define PRIVATE_KEY_FILE "f:\\rsapriv.key"#define PUBLIC_KEY_FILE "f:\\rsapub.key"#else // non-win32 system#define PRIVATE_KEY_FILE "/tmp/avit.data.tmp1"#define PUBLIC_KEY_FILE "/tmp/avit.data.tmp2"#endif#define RSA_PRIKEY_PSW "123"#ifdef WIN32#pragma comment(lib, "libeay32.lib")#pragma comment(lib, "ssleay32.lib")#endif
2.2.2 生成密钥文件
// 生成公钥文件和私钥文件,私钥文件带密码int generate_key_files(const char *pub_keyfile, const char *pri_keyfile, const unsigned char *passwd, int passwd_len){RSA *rsa = NULL;RAND_seed(rnd_seed, sizeof(rnd_seed));rsa = RSA_generate_key(RSA_KEY_LENGTH, 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;}
2.2.3 打开公钥
// 打开公钥文件,返回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;}
2.2.4 打开私钥
// 打开私钥文件,返回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;}
2.2.5 公钥加密函数
// 使用密钥加密,这种封装格式只适用公钥加密,私钥解密,这里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;}
2.2.6 私钥解密函数
// 使用密钥解密,这种封装格式只适用公钥加密,私钥解密,这里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;}
2.2.7 测试代码
int main(int argc, char **argv){char origin_text[] = "hello world!";char enc_text[512] = "";char dec_text[512] = "";size_t enc_len = 512;size_t dec_len = 512;// 生成公钥和私钥文件generate_key_files(PUBLIC_KEY_FILE, PRIVATE_KEY_FILE, (const unsigned char *)RSA_PRIKEY_PSW, strlen(RSA_PRIKEY_PSW));EVP_PKEY *pub_key = open_public_key(PUBLIC_KEY_FILE);EVP_PKEY *pri_key = open_private_key(PRIVATE_KEY_FILE, (const unsigned char *)RSA_PRIKEY_PSW);rsa_key_encrypt(pub_key, (const unsigned char *)&origin_text, sizeof(origin_text), (unsigned char *)enc_text, enc_len);rsa_key_decrypt(pri_key, (const unsigned char *)enc_text, enc_len, (unsigned char *)dec_text, dec_len, (const unsigned char *)RSA_PRIKEY_PSW);return 0;}
2.2.7 注意事项
i. 使用EVP方式只能采取公钥加密,私钥解密的方式,反之运行会出错
ii. Win32下注意添加链接时的lib文件,运行时需要相应的dll文件,需添加的lib文件:“libeay32.lib”和“ssleay32.lib”,运行需使用的dll文件:“libeay32.dll”和“ssleay32.dll”。
0 1
- OpenSSL库的RSA使用(上)-EVP方式
- OpenSSL库的RSA使用(下)-rsa函数方式
- OpenSSL库的RSA使用(下)-rsa函数方式
- OpenSSL库的RSA使用
- OPENSSL库的使用-RSA篇
- OPENSSL库的使用-RSA篇
- 使用openssl库EVP编程计算md5值
- 使用openssl库EVP编程计算sha1值
- 使用openssl库EVP编程计算sha256值
- Openssl --RSA加密算法的使用
- Openssl --RSA加密算法的使用
- Openssl --RSA加密算法的使用。
- OpenSSL RSA的简单使用
- 使用Python的OpenSSL库来进行RSA加密
- 使用Python的OpenSSL库来进行RSA加密
- OpenSSL之PKey的EVP封装
- OpenSSL中文手册之EVP库详解
- openssl中aes、rsa算法的使用
- 程序设计实现笔记——性能
- Android:Handler,内部类导致的可能内存泄露
- OpenGL ES在移动设备有限资源下的性能与效果的综合平衡
- python中使用fork创建新的进程
- 串口调试心得
- OpenSSL库的RSA使用(上)-EVP方式
- CHAP验证中的密码问题
- 显示double类型的数据
- java垃圾回收机制
- 模仿Excel的窗口冻结功能
- Adobe DPS Storefront开发
- 扫描线种子填充算法
- python中使用threading进行多线程编程
- 利用memset实现(除-1、0)数组的初始化的问题