2014-12-09 3 views
1

C++에서 OpenSSL을 사용하여 RSA 키 쌍을 테스트하려고합니다. 텍스트를 암호화하고 즉시 해독합니다. 암호화가 성공적으로 완료되었지만 해독은 항상 -1을 반환합니다. 오류 번호는 다음과 같습니다rsa_private_decrypt가 -1을 반환 함, 0x0306B067 오류가 발생했습니다.

0306B067:lib(3):func(107):reason(103) 
나는 원인을 찾을 수 없습니다

은 ... 코드는 다음과 같습니다

char* text = "hello!!!"; 
unsigned char * cipher ; 
unsigned char * decipher ; 
int size = RSA_size(prvKey); 
cipher = (unsigned char *)malloc(size); 
decipher = (unsigned char *)malloc(size); 
int cipherres = RSA_public_encrypt(size - 11/*strlen(text)*/,(unsigned char*)text,cipher,pubKey,RSA_PKCS1_PADDING); 

int decipherres = RSA_private_decrypt(size,cipher,decipher,prvKey,RSA_PKCS1_PADDING); 
if (decipherres == -1) 

RSA 키 쌍 RSA_generate_key_ex() 기능을 사용하여 befor을 생성하고 키 쌍의 pubKey에를 및 prvKey.

답변

0

나는이 라인의 모양을 좋아하지 않는다 :

INT cipherres = RSA_public_encrypt (크기 - 11/나 strlen (텍스트)/...

당신은해야한다 이전에 해봤 던 텍스트의 길이를 사용하여 11을 어디에서 가져 왔는지 모르겠지만 코드의 매직 번호는 악취가납니다.

시도해보기 :

INT cipherres = RSA_public_encrypt (나 strlen (텍스트), ... 또한

, RSA_public_encrypt here에 대한 설명서를 참조하여 다음 줄을 잘못 같습니다

INT 크기 = RSA_size (prvKey);

정의에 따라 prvKey와 pubKey가 같은 크기입니까? 그렇지 않은 경우 공개 키를 사용하여 암호화 전에 크기를 확인하십시오.

int size = RSA_size (pubKey);

그런 다음 해독 버퍼를 prvKey 및 malloc 크기로 따로 가져와야 할 수 있습니다.

+0

먼저 답을 알려 주셔서 감사합니다. 전에 strlen (txt)을 사용했지만 결과는 같았습니다. 링크시 RSA_public_ecnrypt 문서에서 "flen은 PKCS # 1 v1.5 기반 패딩 모드의 경우 RSA_size (rsa) - 11보다 작아야합니다"라고 말하면이 크기를 사용합니다. 난 RSA_size() muduluse 크기를 반환하고 공용 키와 개인 키 사이에 차이가 없다고 생각, 내가 틀렸다고 생각합니까? – maryamT

+0

직접 사용해 본 적은 없지만 비슷한 질문을 유용한 답변과 함께 발견했습니다 : http://stackoverflow.com/questions/426463/problem-with-openssl-library. 암호 해독에 대한 반환 값을 제공해야하는 것 같습니다. 이는 의미가 있습니다 - 해독 할 문자 수를 알려줍니다. 암호화 및 암호 해독 버퍼는 괜찮은 크기이므로 생각해야합니다. – Resource

+0

@Resource - 나는 당신에게 upvote를 빚지고있다. 그러나 나는 지금 빠져있다. 그 중 일부는 잘 잡습니다. – jww

0

프로그램에 몇 가지 문제가 있습니다. 그들 중 일부는 @Resource에 의해 지적되었습니다. 이 태그를 C++로 태그 지정 했으므로 여기에는 C++에서 이러한 작업을 수행하는 방법이 있습니다. 당신이 쓴 동일한 기본 프로그램이지만, 많은 결함이 해결되었습니다.

대답은 또한 How to generate RSA private key using OpenSSL?을 RSA 키 쌍 생성에 사용합니다.

OpenSSL에서는 RSA_public_encryptRSA_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 

내 생각은,이 뭔가.

관련 문제