java实现gpg加密代码,让GPG解密工作在Java(Bouncy Castle)

let me start by saying I'm extremely new to all of this. What I am trying to do is to use gpg from within Java in order to decrypt an encrypted file.

What I've done successfully:

Had a colleague encrypt a file using my public key and his private key and successfully decrypted it.

Went the other way

Had another colleague try to decrypt a file that wasn't for him: fail (as expected)

My key was generated like this...

(gpg --version tells me I'm using 1.4.5 and I'm using Bouncy Castle 1.47)

gpg --gen-ley

Select option "DSA and Elgamal (default)"

Fill in the other fields and generate a key.

The file was encrypted using my public key and another's secret key. I want to decrypt it. I've written the following Java code to accomplish this. I'm using several deprecated methods, but I can't figure out how to properly implement the factory methods required to use the non-deprecated versions, so if anyone has an idea on implementations of those that I should be using that would be a nice bonus.

Security.addProvider(new BouncyCastleProvider());

PGPSecretKeyRingCollection secretKeyRing = new PGPSecretKeyRingCollection(new FileInputStream(new File("test-files/secring.gpg")));

PGPSecretKeyRing pgpSecretKeyRing = (PGPSecretKeyRing) secretKeyRing.getKeyRings().next();

PGPSecretKey secretKey = pgpSecretKeyRing.getSecretKey();

PGPPrivateKey privateKey = secretKey.extractPrivateKey("mypassword".toCharArray(), "BC");

System.out.println(privateKey.getKey().getAlgorithm());

System.out.println(privateKey.getKey().getFormat());

PGPObjectFactory pgpF = new PGPObjectFactory(

new FileInputStream(new File("test-files/test-file.txt.gpg")));

Object pgpObj = pgpF.nextObject();

PGPEncryptedDataList encryptedDataList = (PGPEncryptedDataList) pgpObj;

Iterator objectsIterator = encryptedDataList.getEncryptedDataObjects();

PGPPublicKeyEncryptedData publicKeyEncryptedData = (PGPPublicKeyEncryptedData) objectsIterator.next();

InputStream inputStream = publicKeyEncryptedData.getDataStream(privateKey, "BC");

So when I run this code I learn that my algorithm and format are as follows for my secret key:

Algorithm: DSA

Format: PKCS#8

And then it breaks on the last line:

Exception in thread "main" org.bouncycastle.openpgp.PGPException: error setting asymmetric cipher

at org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder.decryptSessionData(Unknown Source)

at org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder.access$000(Unknown Source)

at org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder$2.recoverSessionData(Unknown Source)

at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)

at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)

at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)

at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)

at TestBouncyCastle.main(TestBouncyCastle.java:74)

Caused by: java.security.InvalidKeyException: unknown key type passed to ElGamal

at org.bouncycastle.jcajce.provider.asymmetric.elgamal.CipherSpi.engineInit(Unknown Source)

at org.bouncycastle.jcajce.provider.asymmetric.elgamal.CipherSpi.engineInit(Unknown Source)

at javax.crypto.Cipher.init(DashoA13*..)

at javax.crypto.Cipher.init(DashoA13*..)

... 8 more

I'm open to a lot of suggestions here, from "don't use gpg, use x instead" to "don't use bouncy castle, use x instead" to anything in between. Thanks!

解决方案

I've decided to go with a much different approach, which is to forego the use of bouncy castle altogether and simply use a runtime process instead. For me this solution is working and completely removes the complexity surrounding bouncy castle:

String[] gpgCommands = new String[] {

"gpg",

"--passphrase",

"password",

"--decrypt",

"test-files/accounts.txt.gpg"

};

Process gpgProcess = Runtime.getRuntime().exec(gpgCommands);

BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));

BufferedReader gpgError = new BufferedReader(new InputStreamReader(gpgProcess.getErrorStream()));

After doing that you need to remember to drain your input stream as your process is execing or your program will probably hang depending on how much you're outputing. See my answer in this thread (and also that of Cameron Skinner and Matthew Wilson who got me on the proper path) for a bit more context: Calling GnuPG in Java via a Runtime Process to encrypt and decrypt files - Decrypt always hangs

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值