openssl RSA 非对称加解密

13 篇文章 0 订阅
12 篇文章 0 订阅


一直在研究数据加密与解密,一直都没有好好的整理过这些知识,趁现在有时间,稍加整理,以便更多的人知道如何去加解密数据,少走弯路。相关的整理文档可能后续会以电子版pdf的形式发出来。


非对称加密算法安全性确实相对更高,但同样效率/速度也更低一些,毕竟非对称加密的计算量更大。


RSA是目前使用最广的一种非对称加密算法,既可以对数据进行加密解密,也可以对数据进行签名验证。


使用C/C++ 调用openssl/crypt库写了一个简单的代码,同时实现对数据的非对称加密及对数据的签名验证。


<pre name="code" class="cpp">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rsa.h"
#include "err.h"
#include "bn.h"
#include "objects.h" // for RSA_sign() type -- type is defined in this header file 

#define RET_IF_EQ(ret,val,r,msg){\
   if(ret == val){\
        fprintf(stderr,"%s failed \n",msg);\
	return r;\
   }else{\
	fprintf(stderr,"%s success\n",msg);\
   }\
}

int RSA_INFO(RSA *rsa,char *msg){
    fprintf(stderr,"-----------%s----------\n",msg);
    fprintf(stderr,"n:[%s]\n",BN_bn2hex(rsa->n));
    fprintf(stderr,"e:[%s]\n",BN_bn2hex(rsa->e));
    fprintf(stderr,"d:[%s]\n",BN_bn2hex(rsa->d));
    fprintf(stderr,"p:[%s]\n",BN_bn2hex(rsa->p));
    fprintf(stderr,"q:[%s]\n",BN_bn2hex(rsa->q));
    fprintf(stderr,"dmp1:[%s]\n",BN_bn2hex(rsa->dmp1));
    fprintf(stderr,"dmq1:[%s]\n",BN_bn2hex(rsa->dmq1));
    fprintf(stderr,"iqmp:[%s]\n",BN_bn2hex(rsa->iqmp));
    return 0;
}

int init_rsa_key(RSA **rsa,RSA **rsa_pub,RSA **rsa_pri){
    int ret = 0;
     
    BIGNUM *ex = BN_new();
    BN_hex2bn(&ex,"03");
    *rsa = RSA_new();
    RET_IF_EQ(*rsa,NULL,-1,"RSA_new() rsa");
    ret = RSA_generate_key_ex(*rsa,1024,ex,NULL);
    RET_IF_EQ(*rsa,NULL,-1,"rsa_generate_key_ex()");
    ret = RSA_check_key(*rsa);
    fprintf(stderr,"check_key() ret[%d]\n",ret);
    RSA_INFO(*rsa,"rsa");
    *rsa_pub = RSA_new();
    RET_IF_EQ(*rsa_pub,NULL,-1,"RSA_new() rsa_pub");
    *rsa_pri = RSA_new();
    RET_IF_EQ(*rsa_pri,NULL,-1,"RSA_new() rsa_pri");
    
    // rsa_pub
    (*rsa_pub)->n = BN_dup((*rsa)->n);
    (*rsa_pub)->e = BN_dup((*rsa)->e);

    /* 
    (*rsa_pub)->d = BN_dup((*rsa)->d);
    (*rsa_pub)->p = BN_dup((*rsa)->p);
    (*rsa_pub)->q = BN_dup((*rsa)->q);
    (*rsa_pub)->dmp1 = BN_dup((*rsa)->dmp1);
    (*rsa_pub)->dmq1 = BN_dup((*rsa)->dmq1);
    (*rsa_pub)->iqmp = BN_dup((*rsa)->iqmp);
    */

    // rsa_pri
    (*rsa_pri)->n = BN_dup((*rsa)->n);
    (*rsa_pri)->e = BN_dup((*rsa)->e);
    (*rsa_pri)->d = BN_dup((*rsa)->d);
    
    /*
    (*rsa_pri)->p = BN_dup((*rsa)->p);
    (*rsa_pri)->q = BN_dup((*rsa)->q);
    (*rsa_pri)->dmp1 = BN_dup((*rsa)->dmp1);
    (*rsa_pri)->dmq1 = BN_dup((*rsa)->dmq1);
    (*rsa_pri)->iqmp = BN_dup((*rsa)->iqmp);
    */

    return 0;
}

int init_default_key(RSA **rsa,RSA **rsa_pub,RSA **rsa_pri){

   *rsa_pub = RSA_new();
   *rsa_pri = RSA_new();

   static unsigned char n[] = 
"ED636F2A9C9EB0660120049548C384630F7775447EA765E3D8DF5EBEBC0A0F1839DC82C45FB82C2F9A1CE9CD16491B88C5375F2DDDE1ACDDDAD7BBAAEC9FD447B1142488F73ED2B364669D8295089350910FF912F070C3C448014B9C44D32A1321E2B36A26FADCEDA071E532C8796B79FECE25BF971BA520AA4810ACA9E491E9";

    static unsigned char e[] =
"03";

    static unsigned char d[] =
"9E424A1C6869CAEEAB6AADB8DB2D02ECB4FA4E2DA9C4EE97E5EA3F29D2B15F657BE8572D952572CA66BDF1336430BD05D8CF94C93E96733E91E527C7486A8D83D8069A34467D90F3A37133F3206EF894776C54BAF6294582FC4709CEFB0D0C4250CCC0CDA6CD5938657CA5D6E466DD8483A7BB429A9737D4660DDE4783C2A8E3";

    static unsigned char p[] =
"F757805743B0FAE28A370603562FBB9B107B3B558B438E75CA523A364A185F2601FCDF77EBE29129C7070604C97CD59D99F68859F9B6EB103AD6B5B4E9F4EE47";

    static unsigned char q[] =
"F5B2BCE349D17E636505C9928E3262D6CD723EA4F3EF4D0A034482AF82273889A6B2B2BDC0E445EF412FE66BA86249959F5C0481B581E651D65C8D8C7A4BA64F";

    static unsigned char dmp1[] =
"A4E5003A2D20A741B17A0402397527BCB5A77CE3B22D09A3DC36D17986BAEA1956A894FA9D41B61BDA04AEADDBA88E69114F059151249CB57C8F23CDF14DF42F";

    static unsigned char dmq1[] =
"A3CC7DECDBE0FEECEE03DBB70976EC8F33A17F18A29F88B1578301CA56C4D05BC47721D3D5ED83F4D61FEEF270418663BF92ADABCE56998BE43DB3B2FC326EDF";

    static unsigned char iqmp[] =
"AA8591E0EF194760D32CE1397488875FB58A2E7287C7FE8CA4C76F25EA3305F3DD0BFA9FF9D42779D04F6FA2F9F999CFCC174D78920CE7BF4E97E7F750C69FE6";

    (*rsa_pub)->n = BN_new();BN_hex2bn(&((*rsa_pub)->n),n);
    (*rsa_pub)->e = BN_new();BN_hex2bn(&((*rsa_pub)->e),e);
    
    /*
    (*rsa_pri)->d = BN_new();BN_hex2bn(&((*rsa_pri)->d),d);
    (*rsa_pri)->p = BN_new();BN_hex2bn(p,sizeof(p)-1,(*rsa_pri)->p);
    (*rsa_pri)->q = BN_new();BN_hex2bn(q,sizeof(q)-1,(*rsa_pri)->q);
    (*rsa_pri)->dmp1 = BN_new();BN_hex2bn(&((*rsa_pri)->dmp1),dmp1);
    (*rsa_pri)->dmq1 = BN_new();BN_hex2bn(&((*rsa_pri)->dmq1),dmq1);
    (*rsa_pri)->iqmp = BN_new();BN_hex2bn(&((*rsa_pri)->iqmp),iqmp);
    */

    (*rsa_pri)->n = BN_new();BN_hex2bn(&((*rsa_pri)->n),n);
    (*rsa_pri)->d = BN_new();BN_hex2bn(&((*rsa_pri)->d),d);
    (*rsa_pri)->e = BN_new();BN_hex2bn(&((*rsa_pri)->e),e); 
    /*
    (*rsa_pri)->p = BN_new();BN_hex2bn(p,sizeof(p)-1,(*rsa_pri)->p);
    (*rsa_pri)->q = BN_new();BN_hex2bn(q,sizeof(q)-1,(*rsa_pri)->q);
    (*rsa_pri)->dmp1 = BN_new();BN_hex2bn(&((*rsa_pri)->dmp1),dmp1);
    (*rsa_pri)->dmq1 = BN_new();BN_hex2bn(&((*rsa_pri)->dmq1),dmq1);
    (*rsa_pri)->iqmp = BN_new();BN_hex2bn(&((*rsa_pri)->iqmp),iqmp);
    */

    return 0;
}
int ras_test(char *buf1,int len1,RSA *rsa_pub,RSA *rsa_pri){
    int ret = 0;
    int len2,len3;
    int rsa_len = RSA_size(rsa_pub);
    fprintf(stderr,"RSA_size:[%d]\n",rsa_len);
    len2 = len3 = rsa_len;
    char *buf2 = (char *)malloc(rsa_len);
    char *buf3 = (char *)malloc(rsa_len);

    len2 = RSA_public_encrypt(len1,buf1,buf2,rsa_pub,RSA_PKCS1_PADDING);
    fprintf(stderr,"encrypt ret[%d] len1:[%d] len2:[%d]\n",ret,len1,len2);
    len3 = RSA_private_decrypt(len2,buf2,buf3,rsa_pri,RSA_PKCS1_PADDING);
    fprintf(stderr,"decrypt ret[%d] len2:[%d] len3:[%d]\n",ret,len2,len3);

    if(len1 == len3 && memcmp(buf1,buf3,len1)==0){
        fprintf(stderr,"rsa test(public-private) success.\n");
    }else{
        fprintf(stderr,"rsa test(public-private) failed.\n");
    }
    
    memset(buf2,0,rsa_len);
    memset(buf3,0,rsa_len);

    len2 = RSA_private_encrypt(len1,buf1,buf2,rsa_pri,RSA_PKCS1_PADDING);
    fprintf(stderr,"private encrypt ret[%d] len1:[%d] len2:[%d]\n",ret,len1,len2);
    len3 = RSA_public_decrypt(len2,buf2,buf3,rsa_pub,RSA_PKCS1_PADDING);
    fprintf(stderr,"public decrypt ret[%d] len2:[%d] len3:[%d]\n",ret,len2,len3);

    if(len1 == len3 && memcmp(buf1,buf3,len1)==0){
        fprintf(stderr,"rsa test(private-public) success.\n");
    }else{
        fprintf(stderr,"rsa test(private-public) failed.\n");
    }
    // verify
    ret = RSA_sign(NID_sha1,buf1,len1,buf2,&len2,rsa_pri);
    fprintf(stderr,"RSA_sign() ret:[%d] [1:success,0:failed] len2:[%d]\n",ret,len2);
    long err = ERR_get_error();
    ERR_error_string(err,buf3);
    fprintf(stderr,"err:[%d] msg:[%s]\n",err,buf3);

    ret = RSA_verify(NID_sha1,buf1,len1,buf2,len2,rsa_pub);
    fprintf(stderr,"RSA_verify() ret:[%d] [1:success,0:failed]\n",ret);
    err = ERR_get_error();
    ERR_error_string(err,buf3);
    fprintf(stderr,"err:[%d] msg:[%s]\n",err,buf3);

    // error_verify
    ret = RSA_verify(NID_sha1,buf1,len1,buf3,len2,rsa_pub);
    fprintf(stderr,"RSA_verify() ret:[%d] [1:success,0:failed]\n",ret);
    err = ERR_get_error();
    ERR_error_string(err,buf3);
    fprintf(stderr,"err:[%d] msg:[%s]\n",err,buf3);

    free(buf2);
    free(buf3);   
 
    return ret;
}

#define BUF_SIZE 50
int main(int argc, char ** args){

    RSA *rsa = NULL;
    RSA *rsa_pub = NULL;
    RSA *rsa_pri = NULL;
    int ret =  init_rsa_key(&rsa,&rsa_pub,&rsa_pri);
    //int ret = init_default_key(&rsa,&rsa_pub,&rsa_pri);
    
    char *buf1 = (char *)malloc(BUF_SIZE + 128);

    int i,len1;
    len1 = BUF_SIZE;
    for(i=0;i<BUF_SIZE;i++){
	buf1[i] = i%256;
    }

    ras_test(buf1,len1,rsa_pub,rsa_pri);

    RSA_free(rsa);
    RSA_free(rsa_pub);
    RSA_free(rsa_pri);

    return 0;
}
//
// RSA 非对称加密解密,数字签名及验证
//


 

本代码在 openssl-1.0.1k版本下验证通过,之前的一个openssl版本程序一直出不了结果,不确定是否由于测试机器有多个openssl版本,导致此类异常。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值