There's actually no easy way to do this. You can call a program called gpgsm using:
gpgsm -o secret-gpg-key.p12 --export-secret-key-p12 0xXXXXXXXX
openssl pkcs12 -in secret-gpg-key.p12 -nocerts -out gpg-key.pem
openssl pkcs12 -in secret-gpg-key.p12 -nokeys -out gpg-certs.pem
If you insist, then you should look at the gpgsm sourcecode as it's a specially built tool for the job.
The last 2 lines can be done in C++ easily. To load RSA keys you can do:
static int pass_cb(char* buf, int size, int rwflag, void* u)
{
const string pass = reinterpret_cast<char*>(u);
int len = pass.size();
// if too long, truncate
if (len > size)
len = size;
pass.copy(buf, len);
return len;
}
RSA* LoadPrivateKey(const string& pem, const string& pass)
{
BIO_free(bio);
BIO* bio = BIO_new_mem_buf(StringAsVoid(str), -1);
if (!bio)
throw ReadError();
RSA* keypair = PEM_read_bio_RSAPrivateKey(bio, NULL, pass_cb,
StringAsVoid(pass));
if (!keypair)
throw NoKeypairLoaded();
return keypair;
}
If it's a public key then use PEM_read_bio_PKCS7 instead. The above function should recognise it's PKCS.
Maybe sometimes you'll need an EVP object:
class EvpBox
{
public:
EvpBox(RSA* keyp);
~EvpBox();
EVP_PKEY* Key();
private:
EVP_PKEY* evpkey;
};
...
EvpBox::EvpBox(RSA* keyp)
{
evpkey = EVP_PKEY_new();
if (!EVP_PKEY_set1_RSA(evpkey, keyp)) {
throw ReadError();
}
}
EvpBox::~EvpBox()
{
EVP_PKEY_free(evpkey);
}
EVP_PKEY* EvpBox::Key()
{
return evpkey;
}
1HmskBCwhnV8DRvYdpBmDyyTwGc28otPeZ