3

I have a .gpg file and a RSA private key. How can I programatically decrypt it without using operating system? e.g. without using something like Runtime.getRuntime().exec("gpg -decrypt.....");

Libraries I've found all run operating system. Like GnuPG or gnugpg-for-java.

Jens Erat
  • 37,523
  • 16
  • 80
  • 96
Morteza Shahriari Nia
  • 1,392
  • 18
  • 24

3 Answers3

3

As Skyr mentioned: Bouncy Castle is the way to go.

What do you want to do with this key? If your goal is to en- or decrypt files you might want to take a look at bouncy-gpg (shameless plug: I wrote it).

Using secret keys is actually three steps

  1. Parse the key and put it into a PGPSecretKeyRing
  2. Extract the secret key from the keyring
  3. Decrypt it with the password

1. Parsing the exported key

In any case look here for the part that parses keys:

class ...

private PGPSecretKeyRingCollection secretKeyRings = new PGPSecretKeyRingCollection(EMPTY_LIST);

 ...

/**
 * Add a new secret keyring to the public keyrings.
 * .
 * Can read the result of "gpg --export" and "gpg --export -a keyid"
 * .
 * E.g. "gpg --export-secret-key -a keyid":
 * addSecretKey("-----BEGIN PGP PRIVATE KEY BLOCK----- ....".getBytes("US-ASCII")
 * <p>
 * The password is queried via the callback (decryptionSecretKeyPassphraseForSecretKeyId).
 *
 * @param encodedPrivateKey the key ascii armored or binary
 * @throws IOException  IO is dangerous
 * @throws PGPException E.g. this is nor a valid key
 */
public void addSecretKey(byte[] encodedPrivateKey) throws IOException, PGPException {

    if (encodedPrivateKey == null) {
        throw new NullPointerException("encodedPrivateKey must not be null");
    }

    try (
            final InputStream raw = new ByteArrayInputStream(encodedPrivateKey);
            final InputStream decoded = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(raw)
    ) {
        PGPSecretKeyRing pgpPrivate = new PGPSecretKeyRing(decoded, getKeyFingerPrintCalculator());
        this.secretKeyRings = PGPSecretKeyRingCollection.addSecretKeyRing(this.secretKeyRings, pgpPrivate);
    }
}

2. Getting the key from the keyring

       final PGPSecretKeyRingCollection pgpSec = ...
       final PGPSecretKey encryptedKey = pgpSec.getSecretKey(keyID);

3. Decrypting the key

Later you have to decrypt the key using a password like so:

 /**
 * Decrypt an encrypted PGP secret key.
 *
 * @param encryptedKey An encrypted key
 * @param passphrase   The passphrase for the key
 * @return the decrypted secret key
 * @throws PGPException E.g. wrong passphrase
 */
public static PGPPrivateKey extractPrivateKey(PGPSecretKey encryptedKey, final char[] passphrase) throws PGPException {
    LOGGER.debug("Extracting secret key with key ID '0x{}'", Long.toHexString(encryptedKey.getKeyID()));

    PGPDigestCalculatorProvider calcProvider = new JcaPGPDigestCalculatorProviderBuilder()
            .setProvider(BouncyCastleProvider.PROVIDER_NAME).build();

    PBESecretKeyDecryptor decryptor = new JcePBESecretKeyDecryptorBuilder(
            calcProvider).setProvider(BouncyCastleProvider.PROVIDER_NAME)
            .build(passphrase);

    return encryptedKey.extractPrivateKey(decryptor);
}
Jens
  • 570
  • 3
  • 11
  • can't you add your maven jar at a common public maven repository? I don't want to add additional repository. – Mikey Dec 03 '19 at 00:05
  • 1
    The last time I looked it was a real hassle to add something to maven central. Since jcenter is a superset of maven central that was the easiest way to get a wide distribution. But any PR is welcome! – Jens Dec 03 '19 at 05:23
  • Yeah, there are some requirements in order to put it on Maven Repo. But thanks for the library. Pretty straightforward. – Mikey Dec 03 '19 at 18:47
1

The Bouncy Castle library provides (among other features) an OpenPGP implementation. The package org.bouncycastle.openpgp.examples contains several usage examples, one of them showing how to encrypt/decrypt a file using a public/secret key pair (you can have a look at the examples on GrepCode or on the project's Github mirror).

Skyr
  • 980
  • 7
  • 12
  • 1
    See https://github.com/bcgit/bc-java/tree/master/pg/src/main/java/org/bouncycastle/openpgp/examples – splashout Jul 27 '20 at 23:40
  • Are OpenPGP and GnuPG compatible? Edit: > GnuPG is a complete and free implementation of the OpenPGP standard as defined by RFC4880 (also known as PGP). – Brandon Ros Aug 26 '22 at 19:57
1

there are too many examples that I've tried on Bouncy Castle with PGP. The common issue is keyID can't be found in KeyRing.

So, I found @Jens' bouncy-gpg (not sure if he still maintains it.)

Here is his documentation from github.io. It's simple to follow and works! https://neuhalje.github.io/bouncy-gpg/

Mikey
  • 380
  • 4
  • 15