EVP_PKEY 以及 RSA 的区别
来源:互联网 发布:阿里云计算大会 编辑:程序博客网 时间:2024/06/05 04:32
刚学openssl的时候,有许多不明白之处。安装以及其他应用,见其他博文。
在使用RSA的过程中,使用了RSA定义的诸多接口。下面罗列一下。
#include <openssl/rsa.h>#include <openssl/engine.h>RSA * RSA_new(void);void RSA_free(RSA *rsa);//公钥加密int RSA_public_encrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa, int padding);//私钥解密int RSA_private_decrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa, int padding);//私钥加密int RSA_private_encrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa,int padding);//公钥解密int RSA_public_decrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa,int padding);//签名int RSA_sign(int type, unsigned char *m, unsigned int m_len,unsigned char *sigret, unsigned int *siglen, RSA *rsa);//认证int RSA_verify(int type, unsigned char *m, unsigned int m_len,unsigned char *sigbuf, unsigned int siglen, RSA *rsa);//生成RSA *RSA_generate_key(int num, unsigned long e,void (*callback)(int,int,void *), void *cb_arg);//新版int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
关于RSA公钥私钥,可以将其存储在文件中,称为PEM,可以读取和存储。下面是一些常用接口。
RSA *PEM_read_RSAPublicKey(FILE *fp, RSA **x,pem_password_cb *cb, void *u);int PEM_write_RSAPublicKey(FILE *fp, RSA *x);RSA *PEM_read_RSA_PUBKEY(FILE *fp, RSA **x,pem_password_cb *cb, void *u);int PEM_write_RSA_PUBKEY(FILE *fp, RSA *x);
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x,pem_password_cb *cb, void *u);EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x,pem_password_cb *cb, void *u);int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,unsigned char *kstr, int klen,pem_password_cb *cb, void *u);int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,unsigned char *kstr, int klen,pem_password_cb *cb, void *u);
思考一下,为什么openssl既然有了PEM文件的RSA接口,又要定义EVP_PKEY接口呢?为什么既要有BIO方式存取,也要有FILE方式存取呢?经过分析,其实这个不难理解。首先,openssl包含了许多非对称加密算法,每种算法都可以定义自己存取接口。同时,openssl定义了一种统一的接口方式,那就是EVP_PKEY存取接口,这种结构体可以保存各种不同的加密结构体,那样的话,就可以用同样的结构体保存不同的加密结构体。事实上,我跟进源代码,发现RSA的接口其实调用了EVP_PKEY的接口。因此,各种不同的非对称加密算法,就可以用同一个EVP的底层接口来实现,上层再次封装。这样的做法,可以节省开发时间。
RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb,void *u){EVP_PKEY *pktmp;pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);return pkey_get_rsa(pktmp, rsa);}
同样,openssl有自己的ssl,它定义了自己的一套文件操作方式,那就是BIO,BIO既可以封装用于网络通信的socket,也可以用于文件读取,而且还能够用于加密以及非加密的socket连接。正是如此,所以它既支持FILE存取,也支持BIO存取。看源码就可以看出,其实file的操作就是对bio进行一次封装,如下可以看出。
EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u){BIO *b;EVP_PKEY *ret;if ((b=BIO_new(BIO_s_file())) == NULL){PEMerr(PEM_F_PEM_READ_PRIVATEKEY,ERR_R_BUF_LIB);return(0);}BIO_set_fp(b,fp,BIO_NOCLOSE);ret=PEM_read_bio_PrivateKey(b,x,cb,u);BIO_free(b);return(ret);}
下面分析EVP_PKEY。其实openssl将关于PEM的操作有一个统一的操作,将这些结构都保存在EVP_PKEY中。因为其实非对称加密方式有好几种:RSA、DSA、ECC,他们的原理不同,因此其密钥结构不同。下面是密钥生成函数,可以看出,密钥存在各自的不同的结构体中。
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);int DSA_generate_key(DSA *dsa);int EC_KEY_generate_key(EC_KEY *eckey);int DH_generate_key(DH *dh);
RSA 结构rsa.h中,其中{n,e} 表示公钥,{n, d}表示私钥
struct rsa_st{.....BIGNUM *n;BIGNUM *e;BIGNUM *d;BIGNUM *p;BIGNUM *q;BIGNUM *dmp1;BIGNUM *dmq1;BIGNUM *iqmp;.....};
DSA结构在dsa.h中
struct dsa_st{......BIGNUM *p;BIGNUM *q;/* == 20 */BIGNUM *g;BIGNUM *pub_key; /* y public key */BIGNUM *priv_key; /* x private key */......};
ECC结构在ecc.h
struct ec_key_st {EC_GROUP *group;EC_POINT *pub_key;BIGNUM *priv_key;} /* EC_KEY */;
DH结构体在dh.h中定义
struct dh_st{BIGNUM *p;BIGNUM *g;long length; /* optional */BIGNUM *pub_key;/* g^x */BIGNUM *priv_key;/* x */}
接着分析EVP_KEP结构体,可以看出最有特点的是一个union结构。
struct evp_pkey_st{int type;int save_type;int references;const EVP_PKEY_ASN1_METHOD *ameth;ENGINE *engine;union{char *ptr;#ifndef OPENSSL_NO_RSAstruct rsa_st *rsa;/* RSA */#endif#ifndef OPENSSL_NO_DSAstruct dsa_st *dsa;/* DSA */#endif#ifndef OPENSSL_NO_DHstruct dh_st *dh;/* DH */#endif#ifndef OPENSSL_NO_ECstruct ec_key_st *ec;/* ECC */#endif} pkey;int save_parameters;STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */} /* EV
在union结构中分别定义rsa、dsa、dh、ec,这些不难理解,定义共用体的目的是节省内存,因为每次这个结构体只为一个非对称密码算法服务。而为什么定义一个ptr呢?这边封装的技巧就在这,ptr指向密钥结构的地址。不管生产的密钥是哪一种类型结构,将其强制转化为char* 赋值给ptr。而当我们调用时,我们根据type的类型,直接进行调用。比如说:EVP_KEY *pkey;pkey->pkey.rsa;直接就将ptr当成rsa类型操作。这就是共用体的好处。
参考资料:
http://fossies.org/dox/openssl-1.0.1f/index.html
阅读全文
0 0
- EVP_PKEY 以及 RSA 的区别
- DSA与RSA的区别
- DES、AES、RSA的区别
- RSA算法和DH算法的区别
- RSA 密钥生成工具,以及出现的问题
- 关于RSA算法的资料阅读以及程序编写
- 对称加密与非对称加密,以及RSA的原理
- RSA算法的理解以及实现(C++)
- 第二周__“RSA”、“数字签名”、“公钥”、“DES”等4个名词的解释以及公钥加密 与 数字签名 之间的联系与区别
- RSA和DES区别
- RSA加密解密和签名验证机制以及其区别和联系
- RSA公钥和私钥的区别
- Android 关于RSA 加密和签名的区别
- null,""以及" "的区别
- RSA加密算法实现以及C#
- RSA算法以及MD5算法
- RSA算法以及数学基础
- rsa 签名和加密 区别
- python学习之——import sys模块
- findbugs与sonar
- 大闯关数学部分过关心得
- mabatis 传的参数为list,xml文件查询时可以用foreach
- 求一个数二进制中1的个数
- EVP_PKEY 以及 RSA 的区别
- 基于完全二叉树木形成的二叉树顺序存储-数据结构(13)
- ubuntu 12.04安装配置samba
- action分页处理
- 并发容器和框架
- 如何更好的找到你需要的资料
- shiro学习笔记2——组件之身份验证
- tslib 安装教程
- Windows如何修改MySQL用户root密码