프로그램에 몇 가지 문제가 있습니다. 그들 중 일부는 @Resource에 의해 지적되었습니다. 이 태그를 C++로 태그 지정 했으므로 여기에는 C++에서 이러한 작업을 수행하는 방법이 있습니다. 당신이 쓴 동일한 기본 프로그램이지만, 많은 결함이 해결되었습니다.
대답은 또한 How to generate RSA private key using OpenSSL?을 RSA 키 쌍 생성에 사용합니다.
OpenSSL에서는 RSA_public_encrypt
및 RSA_private_decrypt
대신 EVP 인터페이스를 사용할 것을 권장합니다. OpenSSL wiki의 EVP Asymmetric Encryption and Decryption도 참조하십시오.
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <string>
#include <memory>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <cassert>
#define ASSERT assert
using BN_ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>;
using RSA_ptr = std::unique_ptr<RSA, decltype(&::RSA_free)>;
int main(int argc, char* argv[])
{
////////////////////////////////////////////////////////////
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
////////////////////////////////////////////////////////////
RSA_ptr privKey(RSA_new(), ::RSA_free);
RSA_ptr pubKey(RSA_new(), ::RSA_free);
BN_ptr bn(BN_new(), ::BN_free);
int rc;
// Set exponent
rc = BN_set_word(bn.get(), RSA_F4);
ASSERT(rc == 1);
if (rc != 1)
{
std::ostringstream msg;
msg << "BN_set_word failed. Error 0x" << std::hex << ERR_get_error();
throw std::runtime_error(msg.str());
}
// Generate private key
rc = RSA_generate_key_ex(privKey.get(), 2048, bn.get(), NULL);
ASSERT(rc == 1);
if (rc != 1)
{
std::ostringstream msg;
msg << "RSA_generate_key_ex failed. Error 0x" << std::hex << ERR_get_error();
throw std::runtime_error(msg.str());
}
// Create a public key from private key
pubKey.reset(RSAPublicKey_dup(privKey.get()));
////////////////////////////////////////////////////////////
std::string text = "Yoda said, Do or do not. There is no try.";
std::string cipher, decipher;
int size = RSA_size(privKey.get());
ASSERT(size >= 0);
if (size < 0)
{
std::ostringstream msg;
msg << "RSA_size failed. Error 0x" << std::hex << ERR_get_error();
throw std::runtime_error(msg.str());
}
// 41 due to RSA_PKCS1_OAEP_PADDING
ASSERT(text.length() + 41 < size);
if (text.length() + 41 >= size)
{
std::ostringstream msg;
msg << "Plain text length is too long for modulus and padding";
throw std::runtime_error(msg.str());
}
// Resize to maximum size
cipher.resize(size);
decipher.resize(size);
rc = RSA_public_encrypt(text.length(),(unsigned char*)&text[0],
(unsigned char*)&cipher[0], pubKey.get(), RSA_PKCS1_OAEP_PADDING);
ASSERT(rc >= 0);
if (rc < 0)
{
std::ostringstream msg;
msg << "RSA_public_encrypt failed. Error 0x" << std::hex << ERR_get_error();
throw std::runtime_error(msg.str());
}
// Resize now that we know the size
cipher.resize(size);
rc = RSA_private_decrypt(cipher.length(), (unsigned char*)&cipher[0],
(unsigned char*)&decipher[0], privKey.get(), RSA_PKCS1_OAEP_PADDING);
ASSERT(rc >= 0);
if (rc < 0)
{
std::ostringstream msg;
msg << "RSA_private_decrypt failed. Error 0x" << std::hex << ERR_get_error();
throw std::runtime_error(msg.str());
}
std::cout << "Message: " << text << std::endl;
std::cout << "Recovered: " << decipher << std::endl;
return 0;
}
프로그램에는 라이브러리의 암호화 부분 만 있으면됩니다. 이 프로그램은 OpenSSL 1.0에서 제작되었습니다.2 소스 디렉토리 :
$ g++ -std=c++11 -DNDEBUG -I ./include test.cxx ./libcrypto.a -ldl -o test.exe
$ ./test.exe
Message: Yoda said, Do or do not. There is no try.
Recovered: Yoda said, Do or do not. There is no try.
이에 대해 :
0306B067:lib(3):func(107):reason(103)
시도 : pubKey
또는 privKey
문제
$ openssl errstr 0306B067
error:0306B067:bignum routines:BN_div:div by zero
내 생각은,이 뭔가.
먼저 답을 알려 주셔서 감사합니다. 전에 strlen (txt)을 사용했지만 결과는 같았습니다. 링크시 RSA_public_ecnrypt 문서에서 "flen은 PKCS # 1 v1.5 기반 패딩 모드의 경우 RSA_size (rsa) - 11보다 작아야합니다"라고 말하면이 크기를 사용합니다. 난 RSA_size() muduluse 크기를 반환하고 공용 키와 개인 키 사이에 차이가 없다고 생각, 내가 틀렸다고 생각합니까? – maryamT
직접 사용해 본 적은 없지만 비슷한 질문을 유용한 답변과 함께 발견했습니다 : http://stackoverflow.com/questions/426463/problem-with-openssl-library. 암호 해독에 대한 반환 값을 제공해야하는 것 같습니다. 이는 의미가 있습니다 - 해독 할 문자 수를 알려줍니다. 암호화 및 암호 해독 버퍼는 괜찮은 크기이므로 생각해야합니다. – Resource
@Resource - 나는 당신에게 upvote를 빚지고있다. 그러나 나는 지금 빠져있다. 그 중 일부는 잘 잡습니다. – jww