2021SC@SDUSC
17.1 RSA介绍
RSA算法是一个广泛使用的公钥算法。
其密钥包括公钥和私钥。它能用于数字签名、身份认证以及密钥交换。
RSA密钥长度一般使用1024位或者更高。RSA密钥信息主要包括[1]:
n : 模数
e : 公钥指数
d : 私钥指数
p : 最初的大素数
q : 最初的大素数
dmp1 : e*dmp1 = 1 (mod (p-1))
dmq1 : e*dmq1 = 1 (mod (q-1))
iqmp : q*iqmp = 1 (mod p )
其中,公钥为n和e;私钥为n和d。
在实际应用中,公钥加密一般用来协商密钥;私钥加密一般用来签名。
17.2 openssl的RSA实现
Openssl的RSA实现源码在crypto/rsa目录下。它实现了RSA PKCS1标准。主要源码如下:
1) rsa.h
定义RSA数据结构以及RSA_METHOD,定义了RSA的各种函数。
2) rsa_asn1.c
实现了RSA密钥的DER编码和解码,包括公钥和私钥。
3) rsa_chk.c
RSA密钥检查。
4) rsa_eay.c
Openssl实现的一种RSA_METHOD,作为其默认的一种RSA计算实现方式。
此文件未实现rsa_sign、rsa_verify和rsa_keygen回调函数。
5)rsa_err.c
RSA错误处理。
6)rsa_gen.c
RSA密钥生成,如果RSA_METHOD中的rsa_keygen回调函数不为空,则调用它,
否则调用其内部实现。
7)rsa_lib.c
主要实现了RSA运算的四个函数(公钥/私钥,加密/解密),
它们都调用了RSA_METHOD中相应都回调函数。
8)rsa_none.c
实现了一种填充和去填充。
9)rsa_null.c
实现了一种空的RSA_METHOD。
10) rsa_oaep.c
实现了oaep填充与去填充。
11)rsa_pk1.
实现了pkcs1填充与去填充。
12)rsa_sign.c
实现了RSA的签名和验签。
13)rsa_ssl.c
实现了ssl填充。
14)rsa_x931.c
实现了一种填充和去填充。
17.3 RSA签名与验证过程
RSA签名过程如下:
- 对用户数据进行摘要;
2)构造X509_SIG结构并DER编码,其中包括了摘要算法以及摘要结果。
3)对2)的结果进行填充,填满RSA密钥长度字节数。
比如1024位RSA密钥必须填满128字节。具体的填充方式由用户指定。
4)对3)的结果用RSA私钥加密。
RSA_eay_private_encrypt函数实现了3)和4)过程。
RSA验签过程是上述过程的逆过程,如下:
- 对数据用RSA公钥解密,得到签名过程中2)的结果。
- 去除1)结果的填充。
- 从2)的结果中得到摘要算法,以及摘要结果。
- 将原数据根据3)中得到摘要算法进行摘要计算。
5)比较4)与签名过程中1)的结果。
RSA_eay_public_decrypt实现了1)和2)过程。
17.4 数据结构
RSA主要数据结构定义在crypto/rsa/rsa.h中:
17.4.1 RSA_METHOD
struct rsa_meth_st {
const char *name;
int (*rsa_pub_enc)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding);
int (*rsa_pub_dec)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding);
int (*rsa_priv_enc)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding);
int (*rsa_priv_dec)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding);
/* 其他函数 */
int (*rsa_sign)(int type, const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
int (*rsa_verify)(int dtype,const unsigned char *m, unsigned int m_length,
unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
}