[英]Reading and writing rsa keys to a pem file in C
我正在編寫一個C程序來生成RSA密鑰,並將其寫入文件,然后從中讀取。 作業需要我以openssl格式生成文件。 因此,我選擇了PEM。 現在,我具有以下用於創建文件的功能
rsa = RSA_new();
// These 3 keys are generated beforehand
rsa->e = e;
rsa->n = n;
rsa->d = d;
fp = fopen(pubkey_file, "w");
if(!PEM_write_RSAPublicKey(fp, rsa))
{
printf("\n%s\n", "Error writing public key");
}
fflush(fp);
fclose(fp);
fp = fopen(privkey_file, "w");
// pRsaKey = EVP_PKEY_new();
// EVP_PKEY_assign_RSA(pRsaKey, rsa);
if(!PEM_write_RSAPrivateKey(fp, rsa, NULL, 0, 0, NULL, NULL))
// if (!PEM_write_PrivateKey(fp, pRsaKey, NULL, NULL, 0, 0, NULL))
{
printf("\n%s\n", "Error writing private key");
}
fflush(fp);
fclose(fp);
這是讀取文件的功能
rsa = RSA_new();
fp = fopen(pubkey_file, "r");
if(PEM_read_RSAPublicKey(fp, &rsa, NULL, NULL) == NULL)
{
printf("\n%s\n", "Error Reading public key");
return;
}
fclose(fp);
BN_bn2bin(rsa->n, (unsigned char *)modulus);
BN_bn2bin(rsa->e, (unsigned char *)exp);
printf("\n%s\n%s\n", exp, modulus);
RSA_free(rsa);
// pRsaKey = EVP_PKEY_new();
fp = fopen(privkey_file, "r");
if(fp)
// if((PEM_read_PrivateKey(fp, &pRsaKey, NULL, NULL)) == NULL)
if((PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL)) == NULL)
{
printf("\n%s\n", "Error Reading private key");
return;
}
// rsa = RSA_new();
// rsa = EVP_PKEY_get1_RSA(pRsaKey);
fclose(fp);
根據需要寫入和讀取公共密鑰,但是證明密鑰失敗。 我嘗試同時使用rsa和evp(在上面的代碼中對此進行了注釋)進行編寫。 但是,兩者都失敗了。 我無法理解為什么會發生這種情況,也無法嘗試找到調試該問題的方法。 任何人都可以為此提供一些指示嗎?
RSA密鑰是對稱的,您可以將它們中的任何一個用作私鑰或公鑰,這只是您的選擇(但DSA密鑰不是對稱的)。 下面的程序生成兩個2048位長的RSA密鑰,然后將它們保存到文件中並將其讀回到內存中。 那應該給您想法怎么做。
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
const char* pcszPassphrase = "open sezamee";
static void gen_callback(int iWhat, int inPrime, void* pParam);
static void init_openssl(void);
static void cleanup_openssl(void);
static int passwd_callback(char *pcszBuff,int size,int rwflag, void *pPass);
static EVP_PKEY* create_rsa_key(void);
static void handle_openssl_error(void);
int main(int argc, char **argv)
{
int iRet = EXIT_SUCCESS;
EVP_PKEY* pPrivKey = NULL;
EVP_PKEY* pPubKey = NULL;
FILE* pFile = NULL;
const EVP_CIPHER* pCipher = NULL;
init_openssl();
pPrivKey = create_rsa_key();
pPubKey = create_rsa_key();
if(pPrivKey && pPubKey)
{/* Save the keys */
if((pFile = fopen("privkey.pem","wt")) && (pCipher = EVP_aes_256_cbc()))
{
if(!PEM_write_PrivateKey(pFile,pPrivKey,pCipher,
(unsigned char*)pcszPassphrase,
(int)strlen(pcszPassphrase),NULL,NULL))
{
fprintf(stderr,"PEM_write_PrivateKey failed.\n");
handle_openssl_error();
iRet = EXIT_FAILURE;
}
fclose(pFile);
pFile = NULL;
if(iRet == EXIT_SUCCESS)
{
if((pFile = fopen("pubkey.pem","wt")) && PEM_write_PUBKEY(pFile,pPubKey))
fprintf(stderr,"Both keys saved.\n");
else
{
handle_openssl_error();
iRet = EXIT_FAILURE;
}
if(pFile)
{
fclose(pFile);
pFile = NULL;
}
}
}
else
{
fprintf(stderr,"Cannot create \"privkey.pem\".\n");
handle_openssl_error();
iRet = EXIT_FAILURE;
if(pFile)
{
fclose(pFile);
pFile = NULL;
}
}
if(iRet == EXIT_SUCCESS)
{/* Read the keys */
EVP_PKEY_free(pPrivKey);
pPrivKey = NULL;
EVP_PKEY_free(pPubKey);
pPubKey = NULL;
if((pFile = fopen("privkey.pem","rt")) &&
(pPrivKey = PEM_read_PrivateKey(pFile,NULL,passwd_callback,(void*)pcszPassphrase)))
{
fprintf(stderr,"Private key read.\n");
}
else
{
fprintf(stderr,"Cannot read \"privkey.pem\".\n");
handle_openssl_error();
iRet = EXIT_FAILURE;
}
if(pFile)
{
fclose(pFile);
pFile = NULL;
}
if((pFile = fopen("pubkey.pem","rt")) &&
(pPubKey = PEM_read_PUBKEY(pFile,NULL,NULL,NULL)))
{
fprintf(stderr,"Public key read.\n");
}
else
{
fprintf(stderr,"Cannot read \"pubkey.pem\".\n");
handle_openssl_error();
iRet = EXIT_FAILURE;
}
}
}
if(pPrivKey)
{
EVP_PKEY_free(pPrivKey);
pPrivKey = NULL;
}
if(pPubKey)
{
EVP_PKEY_free(pPubKey);
pPubKey = NULL;
}
cleanup_openssl();
return iRet;
}
EVP_PKEY* create_rsa_key(void)
{
RSA *pRSA = NULL;
EVP_PKEY* pKey = NULL;
pRSA = RSA_generate_key(2048,RSA_3,gen_callback,NULL);
pKey = EVP_PKEY_new();
if(pRSA && pKey && EVP_PKEY_assign_RSA(pKey,pRSA))
{
/* pKey owns pRSA from now */
if(RSA_check_key(pRSA) <= 0)
{
fprintf(stderr,"RSA_check_key failed.\n");
handle_openssl_error();
EVP_PKEY_free(pKey);
pKey = NULL;
}
}
else
{
handle_openssl_error();
if(pRSA)
{
RSA_free(pRSA);
pRSA = NULL;
}
if(pKey)
{
EVP_PKEY_free(pKey);
pKey = NULL;
}
}
return pKey;
}
void gen_callback(int iWhat, int inPrime, void* pParam)
{
char c='*';
switch(iWhat)
{
case 0: c = '.'; break;
case 1: c = '+'; break;
case 2: c = '*'; break;
case 3: c = '\n'; break;
}
fprintf(stderr,"%c",c);
}
int passwd_callback(char *pcszBuff,int size,int rwflag, void *pPass)
{
size_t unPass = strlen((char*)pPass);
if(unPass > (size_t)size)
unPass = (size_t)size;
memcpy(pcszBuff, pPass, unPass);
return (int)unPass;
}
void init_openssl(void)
{
if(SSL_library_init())
{
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
RAND_load_file("/dev/urandom", 1024);
}
else
exit(EXIT_FAILURE);
}
void cleanup_openssl(void)
{
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
ERR_remove_thread_state(0);
EVP_cleanup();
}
void handle_openssl_error(void)
{
ERR_print_errors_fp(stderr);
}
sirgeorge給出的答案在守則中有誤。 create_rsa_key
不應被調用兩次。 如果調用兩次,則私鑰沒有匹配的公鑰。 這導致解密期間的問題。 main
方法需要修改
RSA *pRSA = NULL;
pRSA = RSA_generate_key(2048,RSA_3,gen_callback,NULL);
pPrivKey = create_rsa_key(pRSA);
pPubKey = create_rsa_key(pRSA);
create_rsa_key
需要的create_rsa_key
EVP_PKEY* create_rsa_key(RSA *pRSA)
{
EVP_PKEY* pKey = NULL;
pKey = EVP_PKEY_new();
if(pRSA && pKey && EVP_PKEY_assign_RSA(pKey,pRSA))
{
/* pKey owns pRSA from now */
if(RSA_check_key(pRSA) <= 0)
{
fprintf(stderr,"RSA_check_key failed.\n");
handle_openssl_error();
EVP_PKEY_free(pKey);
pKey = NULL;
}
}
else
{
handle_openssl_error();
if(pRSA)
{
RSA_free(pRSA);
pRSA = NULL;
}
if(pKey)
{
EVP_PKEY_free(pKey);
pKey = NULL;
}
}
return pKey;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.