How can I import a key in PEM format (not OpenPGP) into GPG?

gpg
5,634

Although underlying crypto primitives are similar, PGP file (packet) formats including keys are very different from those used by OpenSSL (mostly ASN.1 and PEM). You don't say so, but this appears to be an RSA key. If Java is okay for you, it can do that using BCPROV plus BCPKIX (for PEM) and BCPG (for PGP) from http://www.bouncycastle.org . Adjust name etc to taste.

// nopackage
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.SignatureException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Date;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPEncryptedData;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
import org.bouncycastle.openssl.PEMParser;

/**
 * A simple utility class that converts PEM PKCS8 (OpenSSL) to a RSA PGPPublicKey/PGPSecretKey pair.
 * <p>
 * usage: UnixSE276317 [-a] identity passPhrase inputPEM
 * <p>
 * Where identity is the name to be associated with the public key. The keys are placed 
 * in the files {pub,secret}.asc if -a (armor) is specified and .bpg otherwise.
 */
//modified from package org.bouncycastle.openpgp.examples class RSAPrivateKeyGenerator 
public class UnixSE276317
{
    private static void exportKeyPair(
        OutputStream    secretOut,
        OutputStream    publicOut,
        KeyPair         pair,
        String          identity,
        char[]          passPhrase,
        boolean         armor)
        throws IOException, InvalidKeyException, NoSuchProviderException, SignatureException, PGPException
    {    
        if (armor)
        {
            secretOut = new ArmoredOutputStream(secretOut);
        }

        PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(HashAlgorithmTags.SHA1);
        PGPKeyPair          keyPair = new JcaPGPKeyPair(PGPPublicKey.RSA_GENERAL, pair, new Date());
        PGPSecretKey        secretKey = new PGPSecretKey(PGPSignature.DEFAULT_CERTIFICATION, keyPair, identity, sha1Calc, null, null, 
                new JcaPGPContentSignerBuilder(keyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1), 
                new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.CAST5, sha1Calc).setProvider("BC").build(passPhrase));

        secretKey.encode(secretOut);

        secretOut.close();

        if (armor)
        {
            publicOut = new ArmoredOutputStream(publicOut);
        }

        PGPPublicKey    key = secretKey.getPublicKey();

        key.encode(publicOut);

        publicOut.close();
    }

    public static void main(
        String[] args)
        throws Exception
    {
        Security.addProvider(new BouncyCastleProvider());

        //KeyPairGenerator    kpg = KeyPairGenerator.getInstance("RSA", "BC");

        //kpg.initialize(1024);

        //KeyPair                    kp = kpg.generateKeyPair();

        int flag = args.length > 0 && args[0].equals("-a")? 1: 0;

        if (args.length != flag+3)
        {
            System.out.println("UnixSE276317 [-a] identity passPhrase inputPEM");
            System.exit(0);
        }

        // adapted from org.bouncycastle.openssl.PEMParser$PrivateKeyParser+RSAKeyPairParser
        FileReader rdr = new FileReader (args[flag+2]);
        PrivateKeyInfo pk8 = (PrivateKeyInfo) new PEMParser(rdr).readObject();
        rdr.close(); 
        ASN1Sequence seq = (ASN1Sequence) pk8.parsePrivateKey();
        org.bouncycastle.asn1.pkcs.RSAPrivateKey keyStruct = org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(seq);
        KeyFactory fact = KeyFactory.getInstance ("RSA");
        KeySpec privSpec = new PKCS8EncodedKeySpec (pk8.getEncoded());
        KeySpec pubSpec = new RSAPublicKeySpec(keyStruct.getModulus(), keyStruct.getPublicExponent());
        KeyPair kp = new KeyPair (fact.generatePublic(pubSpec), fact.generatePrivate(privSpec));

        String[] suffix = {"bpg","asc"};
        FileOutputStream    out1 = new FileOutputStream("secret."+suffix[flag]);
        FileOutputStream    out2 = new FileOutputStream("pub."+suffix[flag]);
        exportKeyPair(out1, out2, kp, args[flag+0], args[flag+1].toCharArray(), flag>0);
    }
}
Share:
5,634

Related videos on Youtube

spraff
Author by

spraff

Updated on September 18, 2022

Comments

  • spraff
    spraff almost 2 years

    I have data like this:

    -----BEGIN PRIVATE KEY-----
    MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDPzCORz9kUh4yt
    73fiG1amQ16jwjXNzNO0d4xUWlrCP3dTfXnvtF35r2N/5Nefw9CcztBUAZACbwtn
    (... just sample data ...)
    jSYDRr88RZI4QYv9pW0+A8vWS2SJnIPW0fP9mcPOdZXxG/V2rL03YV5xcLCdbuBu
    1tunEWZ5VcjfyEDfP7qZdWjGIYselOg=
    -----END PRIVATE KEY-----
    

    If I run gpg --import it says:

    gpg: no valid OpenPGP data found.
    gpg: Total number processed: 0
    

    How can I get this private key into GPG?

    • Admin
      Admin about 8 years
      Why do you want to do this?
    • Admin
      Admin about 8 years
      The keys are generated by a web application which uses OpenSSL. I want the private key to reside in gpg on a physically separate machine where it will be used in various scripts which are not part of the website.