让我开始说我对这一切非常新鲜.我想要做的是使用
Java中的gpg来解密加密文件.
我成功完成了什么
>如果某位同事使用我的公钥和他的私钥对文件进行加密,并成功解密.
>另一方面
>如果另一个同事尝试解密一个不适合他的文件:失败(如预期)
我的钥匙是这样生成的
(gpg –version告诉我我正在使用1.4.5,我正在使用Bouncy Castle 1.47)
gpg –gen-ley
选择选项“DSA和Elgamal(默认)”
填写其他字段并生成一个密钥.
该文件使用我的公共密钥和另一个密钥加密.我想解密它.我写了以下Java代码来完成这个.我使用了几种不推荐使用的方法,但是我无法弄清楚如何正确实现使用非弃用版本所需的工厂方法,所以如果任何人有一个想法,我应该使用那些将是一个好的奖金
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");
所以当我运行这个代码我知道我的算法和格式如下对我的秘密密钥:
算法:DSA
格式:PKCS#8
然后在最后一行打破:
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)
导致:java.security.InvalidKeyException:传递给ElGamal的未知密钥类型
在org.bouncycastle.jcajce.provider.asymmetric.elgamal.CipherSpi.engineInit(未知来源)
在org.bouncycastle.jcajce.provider.asymmetric.elgamal.CipherSpi.engineInit(未知来源)
在javax.crypto.Cipher.init(DashoA13 * ..)
在javax.crypto.Cipher.init(DashoA13 * ..)
… 8更多
我在这里开放了很多建议,从“不要使用gpg,使用x”来“不要使用弹性城堡,使用x”来代替它之间的任何东西.谢谢!
解决方法
如果有兴趣知道如何使用bouncy castle openPGP库对gpg文件进行加密和解密,请查看以下java代码:
以下是您需要的4种方法:
public static PGPSecretKey readSecretKeyFromCol(InputStream in,long keyId) throws IOException,PGPException { in = PGPUtil.getDecoderStream(in); PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(in,new BcKeyFingerprintCalculator()); PGPSecretKey key = pgpSec.getSecretKey(keyId); if (key == null) { throw new IllegalArgumentException("Can't find encryption key in key ring."); } return key; }
@SuppressWarnings("rawtypes") public static PGPPublicKey readPublicKeyFromCol(InputStream in) throws IOException,PGPException { in = PGPUtil.getDecoderStream(in); PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in,new BcKeyFingerprintCalculator()); PGPPublicKey key = null; Iterator rIt = pgpPub.getKeyRings(); while (key == null && rIt.hasNext()) { PGPPublicKeyRing kRing = (PGPPublicKeyRing) rIt.next(); Iterator kIt = kRing.getPublicKeys(); while (key == null && kIt.hasNext()) { PGPPublicKey k = (PGPPublicKey) kIt.next(); if (k.isEncryptionKey()) { key = k; } } } if (key == null) { throw new IllegalArgumentException("Can't find encryption key in key ring."); } return key; }
public void decryptFile(InputStream in,InputStream secKeyIn,InputStream pubKeyIn,char[] pass) throws IOException,PGPException,InvalidCipherTextException { Security.addProvider(new BouncyCastleProvider()); PGPPublicKey pubKey = readPublicKeyFromCol(pubKeyIn); PGPSecretKey secKey = readSecretKeyFromCol(secKeyIn,pubKey.getKeyID()); in = PGPUtil.getDecoderStream(in); JcaPGPObjectFactory pgpFact; PGPObjectFactory pgpF = new PGPObjectFactory(in,new BcKeyFingerprintCalculator()); Object o = pgpF.nextObject(); PGPEncryptedDataList encList; if (o instanceof PGPEncryptedDataList) { encList = (PGPEncryptedDataList) o; } else { encList = (PGPEncryptedDataList) pgpF.nextObject(); } Iterator<PGPPublicKeyEncryptedData> itt = encList.getEncryptedDataObjects(); PGPPrivateKey sKey = null; PGPPublicKeyEncryptedData encP = null; while (sKey == null && itt.hasNext()) { encP = itt.next(); secKey = readSecretKeyFromCol(new FileInputStream("PrivateKey.asc"),encP.getKeyID()); sKey = secKey.extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass)); } if (sKey == null) { throw new IllegalArgumentException("Secret key for message not found."); } InputStream clear = encP.getDataStream(new BcpublicKeyDataDecryptorFactory(sKey)); pgpFact = new JcaPGPObjectFactory(clear); PGPCompressedData c1 = (PGPCompressedData) pgpFact.nextObject(); pgpFact = new JcaPGPObjectFactory(c1.getDataStream()); PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject(); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); InputStream inLd = ld.getDataStream(); int ch; while ((ch = inLd.read()) >= 0) { bOut.write(ch); } //System.out.println(bOut.toString()); bOut.writeTo(new FileOutputStream(ld.getFileName())); //return bOut; } public static void encryptFile(OutputStream out,String fileName,PGPPublicKey encKey) throws IOException,NoSuchProviderException,PGPException { Security.addProvider(new BouncyCastleProvider()); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP); PGPUtil.writeFileToLiteralData(comData.open(bOut),PGPLiteralData.BINARY,new File(fileName)); comData.close(); PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.TRIPLE_DES).setSecureRandom(new SecureRandom())); cPk.addMethod(new BcpublicKeyKeyEncryptionMethodGenerator(encKey)); byte[] bytes = bOut.toByteArray(); OutputStream cOut = cPk.open(out,bytes.length); cOut.write(bytes); cOut.close(); out.close(); }
现在这里是如何调用/运行上面的:
try { decryptFile(new FileInputStream("encryptedFile.gpg"),new FileInputStream("PrivateKey.asc"),new FileInputStream("PublicKey.asc"),"yourKeyPassword".tocharArray()); PGPPublicKey pubKey = readPublicKeyFromCol(new FileInputStream("PublicKey.asc")); encryptFile(new FileOutputStream("encryptedFileOutput.gpg"),"fileToEncrypt.txt",pubKey); } catch (PGPException e) { fail("exception: " + e.getMessage(),e.getUnderlyingException()); }