Load RSA private key from PEM encoded private key

I am trying to load the RSA private key from std::string , which contains the private key in PEM format, for example:

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

And I am wondering if anyone can help me use this key instead of generating a random case with the following statement.

 CryptoPP::RSA::PrivateKey rsaPrivate; rsaPrivate.GenerateRandomWithKeySize (rnd, 512); 
+6
source share
1 answer

The key is encoded by PEM. You need to remove the PEM header and footer, and then convert from Base64 back to DER / BER and finally use Crypto ++ BERDecodePrivateKey .

There are some related topics on the Crypto ++ wiki for Keys and Formats . Below is the code to perform the conversion (I do not believe that Qaru has a working example in 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 the only check // we have regarding the DER bytes consumed. ASSERT(queue.IsEmpty()); } catch (const Exception& ex) { cerr << ex.what() << endl; exit (1); } 

After downloading the key, you can confirm it with:

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

And print it with

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

If the key is password protected, Crypto ++ cannot decode it. The library lacks support for decryption. In this case, you can convert it to BER / DER using the following OpenSSL command. Then you can use key material with Crypto ++.

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

The sample program wrote a key to the file with this:

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

CopyTo leaves the bytes in the queue for later use. You can upload the file using the ASN.1 tool, for example Gutmann dumpasn1 :

 $ 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. 
+8
source

Source: https://habr.com/ru/post/970767/


All Articles