问题
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
- Parse the key and put it into a
PGPSecretKeyRing
- Extract the secret key from the keyring
- 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