2014-06-12 2 views
5

이 같은 PEM 형식의 개인 키를 포함하는 std::string에서 RSA 개인 키를로드하기 위해 노력하고있어 :로드 RSA 개인 키는 인코딩 된 개인 키

-----BEGIN RSA PRIVATE KEY----- 
MIIBOgIBAAJBAK8Q+ToR4tWGshaKYRHKJ3ZmMUF6jjwCS/u1A8v1tFbQiVpBlxYB 
paNcT2ENEXBGdmWqr8VwSl0NBIKyq4p0rhsCAQMCQHS1+3wL7I5ZzA8G62Exb6RE 
INZRtCgBh/0jV91OeDnfQUc07SE6vs31J8m7qw/rxeB3E9h6oGi9IVRebVO+9zsC 
IQDWb//KAzrSOo0P0yktnY57UF9Q3Y26rulWI6LqpsxZDwIhAND/cmlg7rUz34Pf 
SmM61lJEmMEjKp8RB/xgghzmCeI1AiEAjvVVMVd8jCcItTdwyRO0UjWU4JOz0cnw 
5BfB8cSIO18CIQCLVPbw60nOIpUClNxCJzmMLbsrbMcUtgVS6wFomVvsIwIhAK+A 
YqT6WwsMW2On5l9di+RPzhDT1QdGyTI5eFNS+GxY 
-----END RSA PRIVATE KEY----- 

을 내가 누군가 궁금 다음 문으로 무작위로 생성하는 대신이 키를 사용할 수 있습니다.

CryptoPP::RSA::PrivateKey rsaPrivate; 
rsaPrivate.GenerateRandomWithKeySize (rnd, 512); 
+0

개인 키 암호가 보호되어 있습니까? – jww

+0

아니요, 다른 소스에서 가져 와서이 std :: string에 넣습니다. –

+0

[키 및 형식, PEM 인 코드 키] (http://www.cryptopp.com/)에서 Crypto ++ wiki에 질문이 추가되었습니다. wiki/Keys_and_Formats # PEM_Encoded_Keys) – jww

답변

7

키는 PEM으로 인코딩됩니다. PEM 머리글과 바닥 글을 제거한 다음 Base64에서 DER/BER로 변환하고 마지막으로 Crypto ++의 BERDecodePrivateKey을 사용해야합니다.

Crypto ++ wiki의 주제에 대한 설명은 Keys and Formats입니다. 다음은 변환을 수행하는 코드입니다 (Stack Overflow에는 Crypto ++에서 작동하는 예제가 있습니다.)

string RSA_PRIV_KEY = 
    "-----BEGIN RSA PRIVATE KEY-----\n" 
    "MIIBOgIBAAJBAK8Q+ToR4tWGshaKYRHKJ3ZmMUF6jjwCS/u1A8v1tFbQiVpBlxYB\n" 
    "paNcT2ENEXBGdmWqr8VwSl0NBIKyq4p0rhsCAQMCQHS1+3wL7I5ZzA8G62Exb6RE\n" 
    "INZRtCgBh/0jV91OeDnfQUc07SE6vs31J8m7qw/rxeB3E9h6oGi9IVRebVO+9zsC\n" 
    "IQDWb//KAzrSOo0P0yktnY57UF9Q3Y26rulWI6LqpsxZDwIhAND/cmlg7rUz34Pf\n" 
    "SmM61lJEmMEjKp8RB/xgghzmCeI1AiEAjvVVMVd8jCcItTdwyRO0UjWU4JOz0cnw\n" 
    "5BfB8cSIO18CIQCLVPbw60nOIpUClNxCJzmMLbsrbMcUtgVS6wFomVvsIwIhAK+A\n" 
    "YqT6WwsMW2On5l9di+RPzhDT1QdGyTI5eFNS+GxY\n" 
    "-----END RSA PRIVATE KEY-----"; 

static string HEADER = "-----BEGIN RSA PRIVATE KEY-----"; 
static string FOOTER = "-----END RSA PRIVATE KEY-----"; 

size_t pos1, pos2; 
pos1 = RSA_PRIV_KEY.find(HEADER); 
if(pos1 == string::npos) 
    throw runtime_error("PEM header not found"); 

pos2 = RSA_PRIV_KEY.find(FOOTER, pos1+1); 
if(pos2 == string::npos) 
    throw runtime_error("PEM footer not found"); 

// Start position and length 
pos1 = pos1 + HEADER.length(); 
pos2 = pos2 - pos1; 
string keystr = RSA_PRIV_KEY.substr(pos1, pos2); 

// Base64 decode, place in a ByteQueue 
ByteQueue queue; 
Base64Decoder decoder; 

decoder.Attach(new Redirector(queue)); 
decoder.Put((const byte*)keystr.data(), keystr.length()); 
decoder.MessageEnd(); 

// Write to file for inspection 
FileSink fs("decoded-key.der"); 
queue.CopyTo(fs); 
fs.MessageEnd(); 

try 
{ 
    CryptoPP::RSA::PrivateKey rsaPrivate; 
    rsaPrivate.BERDecodePrivateKey(queue, false /*paramsPresent*/, queue.MaxRetrievable()); 

    // BERDecodePrivateKey is a void function. Here's the only check 
    // we have regarding the DER bytes consumed. 
    ASSERT(queue.IsEmpty()); 
} 
catch (const Exception& ex) 
{ 
    cerr << ex.what() << endl; 
    exit (1); 
} 

키를로드 한 후, 당신은 그것을 확인할 수 있습니다 :

AutoSeededRandomPool prng; 
bool valid = rsaPrivate.Validate(prng, 3); 
if(!valid) 
    cerr << "RSA private key is not valid" << endl; 

그리고 그것을 인쇄 : 키가 암호로 보호되어 경우

cout << "N: " << rsaPrivate.GetModulus() << endl << endl; 
cout << "E: " << rsaPrivate.GetPublicExponent() << endl << endl; 
cout << "D: " << rsaPrivate.GetPrivateExponent() << endl << endl; 

는 다음 암호화는 ++ 디코딩 할 수 있습니다 그것. 라이브러리에는 암호 해독을 수행 할 수있는 지원이 없습니다. 이 경우 다음 OpenSSL 명령을 사용하여 BER/DER로 변환 할 수 있습니다. 그런 다음 Crypto ++에서 키 자료를 사용할 수 있습니다.

FileSink fs("decoded-key.der"); 
queue.CopyTo(fs); 
fs.MessageEnd(); 

CopyTo는 나중에 사용하기 위해 queue의 바이트를 잎 :

openssl pkcs8 -nocrypt -in rsa-key.pem -inform PEM -topk8 -outform DER -out rsa-key.der 

샘플 프로그램이 함께 파일에 키를 썼다. Gutmann의 dumpasn1과 같은 ASN.1 도구를 사용하여 파일을 덤프 할 수 있습니다.

$ dumpasn1 decoded-key.der 
    0 314: SEQUENCE { 
    4 1: INTEGER 0 
    7 65: INTEGER 
     :  00 AF 10 F9 3A 11 E2 D5 86 B2 16 8A 61 11 CA 27 
     :  76 66 31 41 7A 8E 3C 02 4B FB B5 03 CB F5 B4 56 
     :  D0 89 5A 41 97 16 01 A5 A3 5C 4F 61 0D 11 70 46 
     :  76 65 AA AF C5 70 4A 5D 0D 04 82 B2 AB 8A 74 AE 
     :  1B 
74 1: INTEGER 3 
77 64: INTEGER 
     :  74 B5 FB 7C 0B EC 8E 59 CC 0F 06 EB 61 31 6F A4 
     :  44 20 D6 51 B4 28 01 87 FD 23 57 DD 4E 78 39 DF 
     :  41 47 34 ED 21 3A BE CD F5 27 C9 BB AB 0F EB C5 
     :  E0 77 13 D8 7A A0 68 BD 21 54 5E 6D 53 BE F7 3B 
143 33: INTEGER 
     :  00 D6 6F FF CA 03 3A D2 3A 8D 0F D3 29 2D 9D 8E 
     :  7B 50 5F 50 DD 8D BA AE E9 56 23 A2 EA A6 CC 59 
     :  0F 
178 33: INTEGER 
     :  00 D0 FF 72 69 60 EE B5 33 DF 83 DF 4A 63 3A D6 
     :  52 44 98 C1 23 2A 9F 11 07 FC 60 82 1C E6 09 E2 
     :  35 
213 33: INTEGER 
     :  00 8E F5 55 31 57 7C 8C 27 08 B5 37 70 C9 13 B4 
     :  52 35 94 E0 93 B3 D1 C9 F0 E4 17 C1 F1 C4 88 3B 
     :  5F 
248 33: INTEGER 
     :  00 8B 54 F6 F0 EB 49 CE 22 95 02 94 DC 42 27 39 
     :  8C 2D BB 2B 6C C7 14 B6 05 52 EB 01 68 99 5B EC 
     :  23 
283 33: INTEGER 
     :  00 AF 80 62 A4 FA 5B 0B 0C 5B 63 A7 E6 5F 5D 8B 
     :  E4 4F CE 10 D3 D5 07 46 C9 32 39 78 53 52 F8 6C 
     :  58 
     : } 

0 warnings, 0 errors. 
+0

jww, 감사합니다. 대단히 감사합니다. 제대로 작동했습니다. –

+0

감사합니다. @EstebanE. [답변 수락 방법은 무엇입니까?] (https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work)를 참조 할 수도 있습니다. 그것이 그대로, 당신의 질문은 공식적으로 답을 얻지 못했습니다. – jww

+0

다시 한 번 감사드립니다. 그러나 평판이 부족하여 귀하의 회신에 투표 할 수 없습니다. –