rsa加解密在pc电脑端已经有了非常广泛的应用,但是在pc端进行rsa加解密大多数都是使用base64编码格式,而在嵌入式开发中一般进行数据加解密都使用16进制的数据格式,因此要在嵌入式开发中使用rsa加解密就有一个编码转换的问题。
通常我们在嵌入式单片机开发时用的rsa秘钥都是16进制的hex数组,类似于下面这样
char pubkey_n[128]={ //1024 bit RSA 公钥 模数
0x01,0x02,0x03,0x04 ......
}
char pubkey_e[4]={ //1024 bit RSA 公钥 指数
0x00,0x01,0x00,0x01
}
而在linux或者pc环境下用的秘钥通常是.pem后缀的文件。类似下面这种
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/x7JUUCPHGe6y50G4oYpygGoX
M5GVreltOtOEHWhr5qCkNtRVAUrpYdUBj/dOALiKy5rOTp4RKX9b9E+ZxJhYDfeA
l6dSkhe+pAvwem7PkGTvlI+glh1kK7WhXwFPzQNzrLcV51K4sP0RqC8WqMErXx9n
1XCCVAbF3L5KZ4I7OwIDAQAB
-----END PUBLIC KEY-----
如何将 16进制的hex秘钥转换为pem格式呢?
经过一番研究,发现其实也不难,用下面这段代码即可完成
//------------------------------------------------------------------------------
// Funtion: RSA 公钥数组生成openssl 标准 pem 格式证书
// Input : 输入公钥 N和E,和N,E的长度(字节),生成pem证书路径和证书名字path
// Output :
// Return :
// Info :
//------------------------------------------------------------------------------
int RSA_PubKey_Creat(const unsigned char* dn,int dn_len,const unsigned char* de,int de_len,char* path)
{
BIGNUM* n = BN_bin2bn(dn, dn_len, NULL);
BIGNUM* e = BN_bin2bn(de, de_len, NULL);
RSA* rsa = RSA_new();
int ret =0;
ret = RSA_set0_key(rsa, n, e, NULL);
if(ret == 0)
{
printf("RSA Set Key Error !\r\n");
ret = -1;
}
else
{
FILE* file = fopen(path, "w");
PEM_write_RSA_PUBKEY(file, rsa);
fflush(file);
fclose(file);
ret = 1;
}
RSA_free(rsa);
BN_clear_free(e);
BN_clear_free(n);
return ret;
}
使用方法如下
RSA_PubKey_Creat(pubkey_n,128,pubkey_e,4,"/var/volatile/tmp/pubkey.pem");
这样就能在/var/volatile/tmp/路径下生成pubkey.pem,证书文件了。
私钥证书有了,如何进行16进制的数据加解密呢?
void pub_encrypt(char *str, int lenth,char* out,char *path_key)
{
RSA *p_rsa = NULL;
FILE *file = NULL;
if((file = fopen(path_key, "rb")) == NULL)
{
perror("pub key error ");
goto End;
}
if((p_rsa = PEM_read_RSA_PUBKEY(file, NULL,NULL,NULL )) == NULL)
{
ERR_print_errors_fp(stdout);
goto End;
}
memset(out, 0, 256);
if(RSA_public_encrypt(lenth, (unsigned char*)str, (unsigned char*)out, p_rsa,RSA_NO_PADDING) < 0)
{
perror("public_encrypt error ");
goto End;
}
End:
if(p_rsa) RSA_free(p_rsa);
if(file) fclose(file);
}
验证测试
//私钥加密,用公钥解密,解密后out数组内容和in数组内容一致
int main()
{
char in[256];
char out[256];
char enc[256];
int i=0;
for(i=0;i<256;i++)
{
in[i]=i; //随意填充16进制数据进行加密
out[i]=0; //清空
enc[i]=0;
}
RSA_PubKey_Creat(pubkey_n,128,pubkey_e,4,"/var/volatile/tmp/pubkey.pem");、//16进制数组生成私钥 pem文件
pub_encrypt(in, 128,enc,"/var/volatile/tmp/pubkey.pem"); //公钥加密,加密后数据保存在enc数组
pri_decrypt(enc, 128,out,"/var/volatile/tmp/key.pri"); //私钥解密 , 私钥解密,解密后内容在out数组
}
代码基于嵌入式linux,openssl 1.1 版本? 编译验证OK。
|