Decrypt gpg in Java without using Java.Runtime

不羁岁月 提交于 2020-01-04 15:29:11

问题


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.


回答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 (there is no browseable sourcecode on the bouncycastle homepage, but you can have a look at the examples on GrepCode).




回答2:


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);
}



回答3:


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/



来源:https://stackoverflow.com/questions/16244372/decrypt-gpg-in-java-without-using-java-runtime

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!