读取和写入C中的pem文件的rsa键

我正在编写一个C程序来为RSA生成密钥并将它们写入文件然后从中读取。 作业要求我以openssl格式生成文件。 所以,我选择了PEM。 现在,我有以下创建文件的function

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); 

这是读取文件的function

 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  #include  #include  #include  #include  #include  #include  #include  #include  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需要修改

 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; }