OPENSSL库的使用-RSA篇

时间:2021-05-04 18:30:05

一、RSA算法简介

        RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。       RSA公开密钥密码*。所谓的公开密钥密码*就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码*。       RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。 二、RSA算法加解密用到的函数1、RSA基本结构
struct
{
int pad;
long version;
const RSA_METHOD *meth;
ENGINE *engine;
BIGNUM *n; n=p*q
BIGNUM *e; 公开的加密指数,经常为65537(ox10001)
BIGNUM *d; 私钥
BIGNUM *p; 大素数p
BIGNUM *q; 大素数q
BIGNUM *dmp1; d mod (p-1)
BIGNUM *dmq1; d mod (q-1)
BIGNUM *iqmp; (inverse of q) mod p
int references;
int flags;
// ...
}RSA;


2、初始化函数
RSA * RSA_new(void);初始化一个RSA结构

3、RSA私钥产生函数
RSA *RSA_generate_key(int num, unsigned long e,void (*callback)(int,int,void *), void *cb_arg);产生一个模为num位的密钥对,e为公开的加密指数,一般为65537(0x10001),假如后两个参数不为NULL,将有些调用。在产生密钥对之前,一般需要指定随机数种子
 4、判断位数函数
 int RSA_size(const RSA *rsa);返回RSA模的位数,他用来判断需要给加密值分配空间的大小
 5、加解密函数1)公钥加密函数int RSA_public_encrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa, int padding); 2)私钥解密函数int RSA_private_decrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa, int padding);
3)私钥加密函数int RSA_private_encrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa,int padding);
4)公钥解密函数int RSA_public_decrypt(int flen, unsigned char *from,unsigned char *to, RSA *rsa,int padding);
flen为要加/解密信息的长度,from为需要加/解密的信息,to为加/解密后的信息,一般to至少要申请 BN_num_bytes(rsa->n)大的空间。加密时Padding表示填充方式,解密时表示去填充方式。
6、 释放函数
void RSA_free(RSA *rsa);释放一个RSA结构 7、与字符串处理相关函数BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);将s中的len位的正整数转化为大数 三、代码示例1、公钥加密
void CPage4::OnButtonPubDecrypt()
{
// TODO: Add your control notification handler code here
unsigned char rsaN[1024] = {0};
unsigned char rsaD[1024] = {0};
unsigned char rsaE[1024] = {0};
unsigned char public_e[8] = {0};
unsigned char publickey_n[1024] = {0};
unsigned char privatekey_d[1024] = {0};
unsigned char inputdata[1024] = {0};
unsigned char output[1024] = {0};
int e_len = 0;
int n_len = 0;
int d_len = 0;
int inputlen = 0;

UpdateData(TRUE);

m_public_e.Remove(' ');
m_publickey_n.Remove(' ');
m_privatekey_d.Remove(' ');
m_inputdata.Remove(' ');

e_len = m_public_e.GetLength()/2;
n_len = m_publickey_n.GetLength()/2;
d_len = m_privatekey_d.GetLength()/2;
inputlen = m_inputdata.GetLength()/2;

StrToHex(m_public_e,public_e,e_len);
StrToHex(m_publickey_n,publickey_n,n_len);
StrToHex(m_privatekey_d,privatekey_d,d_len);
StrToHex(m_inputdata,inputdata,inputlen);

memcpy(rsaN,publickey_n,n_len);
memcpy(rsaD,privatekey_d,d_len);
memcpy(rsaE,public_e,e_len);

RSA* pRsa = RSA_new();

pRsa->n = BN_bin2bn(rsaN, n_len, NULL);
pRsa->d = BN_bin2bn(rsaD, d_len, NULL);
pRsa->e = BN_bin2bn(rsaE, e_len, NULL);

inputlen=RSA_size(pRsa);

int ret = RSA_public_encrypt(inputlen,inputdata,output, pRsa, RSA_NO_PADDING);
if (ret < 0)
{
MessageBox("公钥加密失败,请检查输入数据是否正确!");
RSA_free(pRsa);
return;
}

RSA_free(pRsa);

HexToStr(output,ret,m_outputdata);

UpdateData(FALSE);
}


 2、私钥解密
void CPage4::OnButtonPriDecrypt()
{
// TODO: Add your control notification handler code here
unsigned char rsaN[1024] = {0};
unsigned char rsaD[1024] = {0};
unsigned char rsaE[1024] = {0};
unsigned char public_e[8] = {0};
unsigned char publickey_n[1024] = {0};
unsigned char privatekey_d[1024] = {0};
unsigned char inputdata[1024] = {0};
unsigned char output[1024] = {0};
int e_len = 0;
int n_len = 0;
int d_len = 0;
int inputlen = 0;

UpdateData(TRUE);

m_public_e.Remove(' ');
m_publickey_n.Remove(' ');
m_privatekey_d.Remove(' ');
m_inputdata.Remove(' ');

e_len = m_public_e.GetLength()/2;
n_len = m_publickey_n.GetLength()/2;
d_len = m_privatekey_d.GetLength()/2;
inputlen = m_inputdata.GetLength()/2;

StrToHex(m_public_e,public_e,e_len);
StrToHex(m_publickey_n,publickey_n,n_len);
StrToHex(m_privatekey_d,privatekey_d,d_len);
StrToHex(m_inputdata,inputdata,inputlen);

memcpy(rsaN,publickey_n,n_len);
memcpy(rsaD,privatekey_d,d_len);
memcpy(rsaE,public_e,e_len);

RSA* pRsa = RSA_new();
pRsa->n = BN_bin2bn(rsaN, n_len, NULL);
pRsa->d = BN_bin2bn(rsaD, d_len, NULL);
pRsa->e = BN_bin2bn(rsaE, e_len, NULL);

//inputlen=RSA_size(pRsa)-11;

int ret = RSA_private_decrypt(inputlen,inputdata,output, pRsa, RSA_NO_PADDING);
if (ret < 0)
{
MessageBox("私钥解密失败,请检查输入数据是否正确!");
RSA_free(pRsa);
return;
}

RSA_free(pRsa);

HexToStr(output,ret,m_outputdata);

UpdateData(FALSE);
}


 3、私钥加密
void CPage4::OnButtonEncrypt()
{
// TODO: Add your control notification handler code here
unsigned char rsaN[1024] = {0};
unsigned char rsaD[1024] = {0};
unsigned char rsaE[1024] = {0};
unsigned char public_e[8] = {0};
unsigned char publickey_n[1024] = {0};
unsigned char privatekey_d[1024] = {0};
unsigned char inputdata[1024] = {0};
unsigned char output[1024] = {0};
int e_len = 0;
int n_len = 0;
int d_len = 0;
int inputlen = 0;

UpdateData(TRUE);

m_public_e.Remove(' ');
m_publickey_n.Remove(' ');
m_privatekey_d.Remove(' ');
m_inputdata.Remove(' ');

e_len = m_public_e.GetLength()/2;
n_len = m_publickey_n.GetLength()/2;
d_len = m_privatekey_d.GetLength()/2;
inputlen = m_inputdata.GetLength()/2;

StrToHex(m_public_e,public_e,e_len);
StrToHex(m_publickey_n,publickey_n,n_len);
StrToHex(m_privatekey_d,privatekey_d,d_len);
StrToHex(m_inputdata,inputdata,inputlen);

memcpy(rsaN,publickey_n,n_len);
memcpy(rsaD,privatekey_d,d_len);
memcpy(rsaE,public_e,e_len);

RSA* pRsa = RSA_new();
pRsa->n = BN_bin2bn(rsaN, n_len, NULL);
pRsa->d = BN_bin2bn(rsaD, d_len, NULL);
pRsa->e = BN_bin2bn(rsaE, e_len, NULL);

inputlen=RSA_size(pRsa);

int ret = RSA_private_encrypt(inputlen,inputdata,output, pRsa, RSA_NO_PADDING);
if (ret < 0)
{
MessageBox("私钥加密失败,请检查输入数据是否正确!");
RSA_free(pRsa);
return;
}

RSA_free(pRsa);

HexToStr(output,ret,m_outputdata);

UpdateData(FALSE);

}


 

4、公钥解密
void CPage4::OnButtonDecrypt()
{
// TODO: Add your control notification handler code here
unsigned char rsaN[1024] = {0};
unsigned char rsaD[1024] = {0};
unsigned char rsaE[1024] = {0};
unsigned char public_e[8] = {0};
unsigned char publickey_n[1024] = {0};
unsigned char privatekey_d[1024] = {0};
unsigned char inputdata[1024] = {0};
unsigned char output[1024] = {0};
int e_len = 0;
int n_len = 0;
int d_len = 0;
int inputlen = 0;

UpdateData(TRUE);

m_public_e.Remove(' ');
m_publickey_n.Remove(' ');
m_privatekey_d.Remove(' ');
m_inputdata.Remove(' ');

e_len = m_public_e.GetLength()/2;
n_len = m_publickey_n.GetLength()/2;
d_len = m_privatekey_d.GetLength()/2;
inputlen = m_inputdata.GetLength()/2;

StrToHex(m_public_e,public_e,e_len);
StrToHex(m_publickey_n,publickey_n,n_len);
StrToHex(m_privatekey_d,privatekey_d,d_len);
StrToHex(m_inputdata,inputdata,inputlen);

memcpy(rsaN,publickey_n,n_len);
memcpy(rsaD,privatekey_d,d_len);
memcpy(rsaE,public_e,e_len);

RSA* pRsa = RSA_new();
pRsa->n = BN_bin2bn(rsaN, n_len, NULL);
pRsa->d = BN_bin2bn(rsaD, d_len, NULL);
pRsa->e = BN_bin2bn(rsaE, e_len, NULL);

//inputlen=RSA_size(pRsa)-11;

int ret = RSA_public_decrypt(inputlen,inputdata,output, pRsa, RSA_NO_PADDING);
if (ret < 0)
{
MessageBox("公钥解密失败,请检查输入数据是否正确!");
RSA_free(pRsa);
return;
}

RSA_free(pRsa);

HexToStr(output,ret,m_outputdata);

UpdateData(FALSE);
}


 
5、产生RSA密钥对
void CPage4::OnButtonRsa()
{
// TODO: Add your control notification handler code here
RSA* key;
unsigned char rsa_n[1024];
unsigned char rsa_d[1024];
char keylen[10];
int len;

UpdateData(TRUE);

strcpy(keylen,m_keylen);
len = atoi(keylen);

key = RSA_new();

key = RSA_generate_key(len,0x10001,NULL,NULL);

BN_bn2bin(key->n,rsa_n ); // 保存公钥
BN_bn2bin(key->d,rsa_d ); // 保存私钥

RSA_free(key);

HexToStr(rsa_n,len/8,m_publickey_n);
HexToStr(rsa_d,len/8,m_privatekey_d);

UpdateData(FALSE);

}