首先最近接到一个项目,这个项目中需要用到RSA的加密解密,因为之前没有接触过,在网上找了些资料,然后自己测试后发现其实使用openssl来进行加解密挺简单的,但是网上百度出来的很多又是一样的,有时候帮助不是很大,所以才想要写下来自己在搞整个加密过程遇到的一些问题,方便自己以后回头查看,也可能会帮到遇到同样的童鞋。
废话不多说,我接到的这个项目呢,有几个地方是需要用到RSA的加解密。1、使用.pfx格式的私钥签名。2、使用.cer的公钥文件进行加密操作。3、使用给定的指数与模进行公钥加密。下面有些自己从网上整理的代码,欢迎批评指正。
1、使用.pfx格式的私钥进行签名(部分代码来源网上):
/* * <pre name="code" class="cpp"><pre name="code" class="cpp">* SrcData:需要加密的字符串
* PriPath:私钥文件(.pfx格式)
* PassWd:私钥文件密码
* SignData:结果
*/
int SignDataByPri(char *SrcData,char *PriPath,char *PassWd,char *SignData)
{
int err;
unsigned int SigLen;
unsigned char SigBuf[128];
EVP_MD_CTX MdCtx;
EVP_PKEY *Pkey = NULL;
FILE *Fp = NULL;
X509 *X509 = NULL;
PKCS12 *P12 = NULL;
STACK_OF(X509) *Ca = NULL;
if(SrcData == NULL || PriPath == NULL){
return false;
}
SSLeay_add_all_algorithms();
ERR_load_crypto_strings();
if (!(Fp = fopen(PriPath, "rb"))) {
printf("读取密钥文件失败\n");
return false;
}
P12 = d2i_PKCS12_fp(Fp, NULL);
fclose (Fp);
if (!P12) {
printf("读取密钥文件失败\n");
return false;
}
if (!PKCS12_parse(P12, PassWd, &Pkey, &X509, &Ca)) {
printf("解包密钥失败\n");
PKCS12_free(P12);
return false;
}
PKCS12_free(P12);
if (Pkey == NULL) {
printf("解包密钥失败\n");
return false;
}
/*签名数据*/
EVP_SignInit (&MdCtx, EVP_sha1()); //签名算法选择sha1
EVP_SignUpdate (&MdCtx, SrcData, strlen(SrcData));
SigLen = 128;
memset(SigBuf,0x00,sizeof(SigBuf));
err = EVP_SignFinal (&MdCtx, SigBuf, &SigLen, Pkey);
if (err != 1) {
printf("签名失败\n");
/*释放相关变量*/
if (Pkey) {
EVP_PKEY_free (Pkey);
}
if (X509) {
X509_free(X509);
}
return false;
}
memcpy(SignData, SigBuf, SigLen);
/*释放相关变量*/
if (Pkey) {
EVP_PKEY_free (Pkey);
}
if (X509) {
X509_free(X509);
}
return true;
}
2、使用.cer的公钥文件对字符串进行加密操作:
/*
* src:需要加密的源字符串
* len:src的长度
* path_key:公钥文件的路径(.cer格式)
*/
int RSAencrypt(char *str,int len,char *path_key,char *Enc)
{
char *p_en;
RSA *p_rsa;
FILE *file;
int flen,rsa_len;
PKCS12* p12 = NULL;
X509 * x509 = NULL;
STACK_OF(X509) *ca = NULL;
EVP_PKEY * pkey = NULL;
if((file=fopen(path_key,"r"))==NULL){
perror("open key file error");
return 0;
}
BIO* b;
b=BIO_new_file(path_key,"r");
x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
if (x509 == NULL) {
printf("读密钥文件 \n");
ERR_print_errors_fp (stderr);
return 0;
}
printf("读密钥文件 [%d]\n",__LINE__);
pkey=X509_get_pubkey(x509);
//将EVP_KEY转成RSA KEY (这步很重要)
p_rsa = EVP_PKEY_get1_RSA(pkey);
rsa_len=RSA_size(p_rsa);
p_en=(unsigned char *)malloc(rsa_len+1);
memset(p_en,0,rsa_len+1);
//网山很多例子这个函数调用时第一个参数使用的是密钥的长度是因为他们加密方式使用RSA_NO_PADDING,如使用RSA_PKCS1_PADDING,len需要填源字符串长度
if(RSA_public_encrypt(len,str,p_en,p_rsa,RSA_PKCS1_PADDING)<0){
printf("加密失败\n");
return 0;
}
memcpy(Enc,p_en,rsa_len);
fclose(file);
free(p_en);
return rsa_len;
}
3、使用给定的指数与模进行公钥加密
/*
* type:一般分为10进制和16进制
* Bnn:模,进制数与type对应
* Bne:通常分为两种RSA_F4和RSA_3(在rsa.h定义)
* in:需要加密的源数据
* out:加密后的密文
*/
int RSAEncryptByModule(int type,char *Bnn,int Bne,unsigned char *in,unsigned char *out )
{
int ret, flen;
BIGNUM *bnn, *bne, *bnd;
unsigned char *out_buf;
bnn = BN_new();
bne = BN_new();
bnd = BN_new();
switch(type){
case 10:
BN_dec2bn(&bnn, Bnn);
BN_set_word(bne, Bne);
break;
case 16:
BN_hex2bn(&bnn, Bnn);
BN_set_word(bne, Bne);
break;
default:
printf("err type\n");
return -1;
}
RSA *r = RSA_new();
r->n = bnn;
r->e = bne;
r->d = bnd;
flen = RSA_size(r);
out_buf = ( unsigned char *)malloc(flen);
memset(out_buf, 0, flen); <pre name="code" class="cpp"> //网山很多例子这个函数调用时第一个参数使用的是密钥的长度是因为他们加密方式使用RSA_NO_PADDING,如使用RSA_PKCS1_PADDING,len需要填源字符串长度
ret = RSA_public_encrypt(strlen(in),in,out_buf,r,RSA_PKCS1_PADDING);
if (ret < 0)
{
printf("Encrypt failed!\n");
return ret;
}
memcpy(out,out_buf,ret);
free(out_buf);
RSA_free(r);
return ret;
} 原文:http://blog.csdn.net/rookie_zhu/article/details/45032475