Crypto ++ Keys and Formats and Crypto ++ RSA Cryptography pages may be of interest.
If you create RSA parameters as follows:
AutoSeededRandomPool rng; InvertibleRSAFunction params; params.GenerateRandomWithKeySize(rng, 2048);
You can use the DEREncode and BERDecode InvertibleRSAFunction to encode and decode all parameters, respectively:
{ FileSink output("rsaparams.dat"); params.DEREncode(output); } InvertibleRSAFunction params2; { FileSource input("rsaparams.dat", true); params2.BERDecode(input); }
To encode / decode private and public material, separately use the DEREncode and BERDecode for RSA::PrivateKey and RSA::PublicKey objects:
// Initialize keys from generated params RSA::PrivateKey rsaPrivate(params); RSA::PublicKey rsaPublic(params); // Write keys to file { FileSink output("rsaprivate.dat"); rsaPrivate.DEREncode(output); } { FileSink output("rsapublic.dat"); rsaPublic.DEREncode(output); } // Read keys from file into new objects RSA::PrivateKey rsaPrivate2; RSA::PublicKey rsaPublic2; { FileSource input("rsaprivate.dat", true); rsaPrivate2.BERDecode(input); } { FileSource input("rsapublic.dat", true); rsaPublic2.BERDecode(input); }
FileSource and FileSink are just examples of source and stream objects that you could use. Encoding / decoding routines accept BufferedTransformation objects as parameters, so you can use any other suitable implementation of this interface.
For example, ArraySink can be used to write data to the memory buffer that you supply, and StringSource (also an alias like ArraySource ) can be used to read from the buffer.
Here's some code showing the use of ArraySink and ArraySource to round off private key material via std::vector<byte> :
RSA::PrivateKey rsaPrivate(params); std::vector<byte> buffer(8192 ); ArraySink arraySink(&buffer[0], buffer.size()); rsaPrivate.DEREncode(arraySink);
(see also @jww answer for an example that avoids a fixed-size buffer using ByteQueue ).
And another example of using std::string to store key material and using the StringSink class to write to it, which avoids some buffer management (the string will be automatically changed according to the amount of data that is encoded). Note that this is still binary data, even if it is in the std::string object.
RSA::PrivateKey rsaPrivate(params); std::string rsaPrivateMaterial; StringSink stringSink(rsaPrivateMaterial); rsaPrivate.DEREncode(stringSink); RSA::PrivateKey rsaPrivate2; StringSource stringSource(rsaPrivateMaterial, true); rsaPrivate2.BERDecode(stringSource);
Alternatively, if you want to control the format yourself, you can use the methods of the InvertibleRSAFunction object or key objects to extract individual parameters (as shown in the "Crypto ++ RSA Cryptography" link above) and use this to retrieve the values to store in your own format :
const Integer& n = params.GetModulus(); const Integer& p = params.GetPrime1(); const Integer& q = params.GetPrime2(); const Integer& d = params.GetPrivateExponent(); const Integer& e = params.GetPublicExponent();
Then they can be restored to a new InvertibleRSAFunction or RSA::*Key instance when reading from a file or container using the appropriate configuration methods ( SetModulus() , SetPrime1() , etc.).