前面一篇讲到了密钥的格式,本文利用密钥进行加密,加密/解密都是类似的,本文只说加密。
密钥加载有两个接口:
PEM_read_RSA_PUBKEY加载PKCS#8文件头格式
PEM_read_bio_RSAPublicKey加载PKCS#1文件头格式
参数没仔细研究,第一个参数为文件句柄即可。
加密接口:
int RSA_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
这个接口有个坑,必须要理解RAS的padding原理才能很好的使用这个接口。
这里要理解一下RSA_PKCS1_PADDING,请参照:
https://blog.csdn.net/qq_21794823/article/details/53084585
Padding有两种,
- 当padding是RSA_NO_PADDING,则from不会被填充。这种用于加密字符传长度等于明文快最大长度的情况(1024的RSA,明文长度128)。
- 当padding是RSA_PKCS1_PADDING时,则使用PKCS1规则对from进行填充,填充的内容是随机值,所以每次加密的结果都不同。当传入字符串长度不够明文快最大长度时,需要使用RSA_PKCS1_PADDING方式,使用RSA_NO_PADDING则会机密失败。
文件加载PEM格式密钥并加密
int file_key_encrypt(void )
{
RSA *rsa = NULL;
FILE *fp = NULL;
int len = 0;
int rsa_len = 0;
int ret = 0,i=0;
char* PUBKEY="pub.key";
char *de = NULL;
char str[128];
char* en=(char*)malloc(1024);
memset(str,0,128);
memcpy(str,"\x54\x85\x9b\x34\x2c\x49\xea\x2a",8);
memset(en,0,1024);
if ((fp = fopen(PUBKEY, "r")) == NULL) {
printf("my_encrypt fopen\n");
return -1;
}
/* 读取公钥PEM,PUBKEY格式PEM使用PEM_read_RSA_PUBKEY函数 */
if ((rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
printf("PEM_read_RSAPublicKey\n");
return -1;
}
RSA_print_fp(stdout, rsa, 0);
len = strlen(str);
rsa_len = RSA_size(rsa);
ret=RSA_public_encrypt(rsa_len, (unsigned char *)str, (unsigned char*)en, rsa, RSA_NO_PADDING);
if(ret < 0) {
printf("RSA_public_encrypt\n");
return -1;
}
printf("en\n");
if(ret > 0)
{
for(i = 0 ; i < ret; i++)
{
printf("x%02x",(unsigned char)en[i]);
}
printf("\n");
}
RSA_free(rsa);
fclose(fp);
return ret;
}
内存加载PEM格式密钥并进行加密
int mem_key_encrypt()
{
int i = 0,len = 0;
char pem_key[512];
memset(pem_key,0,512);
len = key_der_pem(pem_key);
BIO* in = BIO_new_mem_buf((void*)pem_key, len);
if (in == NULL) {
printf("BIO_new_mem_buf failed\n");
return -1;
}
RSA* rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);
if (rsa == NULL) {
ERR_load_crypto_strings();
char errBuf[512];
ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));
printf("load public key failed[%s]\n", errBuf);
return -1;
}
#ifdef debug
//RSA_print_fp(stdout, rsa, 0);
#endif
int keySize = RSA_size(rsa);
char fData[256];
memset(fData,0,256);
memcpy(fData,"12345678",8);
char tData[512];
memset(tData,0,512);
int flen = strlen(fData);
//flen = 15
printf("RSA_public_encrypt:\n");
int ret = RSA_public_encrypt(256, (unsigned char *)fData, (unsigned char *)tData, rsa, RSA_NO_PADDING);
//ret = 128
printf("RSA_public_encrypt ret=%d\n",ret);
if(ret > 0)
{
for(i = 0 ; i < ret; i++)
{
printf("\\x%02x",(unsigned char)tData[i]);
}
printf("\n");
}
BIO_free(in);
RSA_free(rsa);
}
以上代码在ubuntu20.4上编译通过
完整的测试用例代码请关注公众号