PGP文件解密报错unknown hash algorithm:8问题求助
PGP解密时抛出
unknown hash algorithm: 8异常 问题现象
开发PgPEncryptionService时,公钥加密文件功能正常,但解密测试用例抛出如下异常:
[main] INFO com.rxbenefits.service.impl.PGPEncryptionService - Secret key algorithm: 9 org.bouncycastle.openpgp.PGPException: unknown hash algorithm: 8 at org.bouncycastle.openpgp.PGPUtil.getS2kDigestName(Unknown Source) at org.bouncycastle.openpgp.PGPUtil.makeKeyFromPassPhrase(Unknown Source) at org.bouncycastle.openpgp.PGPSecretKey.extractKeyData(Unknown Source) at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(Unknown Source) at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(Unknown Source) at com.rxbenefits.service.impl.PGPEncryptionService.findSecretKey(PGPEncryptionService.java:102) at com.rxbenefits.service.impl.PGPEncryptionService.decryptFile(PGPEncryptionService.java:132) at com.rxbenefits.service.impl.PGPEncryptionServiceTest.testFileEncryption(PGPEncryptionServiceTest.java:55) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:54) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
调试发现密钥算法为9,错误发生在findSecretKey方法的pgpSecKey.extractPrivateKey步骤。
已排查项
- 排除密码错误:创建4组密钥对,密码均为
12345 - 排除加密算法问题:已改用
AES_256
相关代码
解密方法
/** * decrypt the passed in message stream */ @SuppressWarnings("unchecked") public static void decryptFile(InputStream in, OutputStream out, InputStream keyIn, char[] passwd) throws Exception { Security.addProvider(new BouncyCastleProvider()); in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in); PGPObjectFactory pgpF = new PGPObjectFactory(in); PGPEncryptedDataList enc; Object o = pgpF.nextObject(); // the first object might be a PGP marker packet. if (o instanceof PGPEncryptedDataList) { enc = (PGPEncryptedDataList) o; } else { enc = (PGPEncryptedDataList) pgpF.nextObject(); } // find the secret key Iterator<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects(); PGPPrivateKey sKey = null; PGPPublicKeyEncryptedData pbe = null; while (sKey == null && it.hasNext()) { pbe = it.next(); sKey = findSecretKey(keyIn, pbe.getKeyID(), passwd); } if (sKey == null) { throw new IllegalArgumentException("Secret key for message not found."); } InputStream clear = pbe.getDataStream(sKey, "BC"); PGPObjectFactory plainFact = new PGPObjectFactory(clear); Object message = plainFact.nextObject(); PGPObjectFactory pgpFact = null; if (message instanceof PGPCompressedData) { PGPCompressedData cData = (PGPCompressedData) message; pgpFact = new PGPObjectFactory(cData.getDataStream()); message = pgpFact.nextObject(); } if (message instanceof PGPLiteralData) { PGPLiteralData ld = (PGPLiteralData) message; InputStream unc = ld.getInputStream(); int ch; while ((ch = unc.read()) >= 0) { out.write(ch); } } else if (message instanceof PGPOnePassSignatureList) { PGPOnePassSignatureList p1 = (PGPOnePassSignatureList) message; PGPOnePassSignature ops = p1.get(0); PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject(); InputStream unc = ld.getInputStream(); int ch; while ((ch = unc.read()) >= 0) { out.write(ch); } } else { throw new PGPException("Message is not a simple encrypted file - type unknown."); } if (pbe.isIntegrityProtected()) { if (!pbe.verify()) { throw new PGPException("Message failed integrity check"); } } }
获取私钥方法
private static PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass) throws IOException, PGPException, NoSuchProviderException { PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn)); PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID); if (pgpSecKey == null) { return null; } log.info("Secret key algorithm: " + pgpSecKey.getKeyEncryptionAlgorithm()); return pgpSecKey.extractPrivateKey(pass, "BC"); }
测试用例
@Test public void testFileEncryption() throws Exception { // create unencrypted file String tempPath = "temp"; FileRepo fileRepo = new FileRepo(); fileRepo.setEncryptionKeyNo(123L); // Create the unencrypted file File unencryptedFile = new File("unencrypted.txt"); try (PrintWriter writer = new PrintWriter(unencryptedFile)) { writer.println("Hello, world!"); } // Encrypt the file File encryptedFile = new File(tempPath + unencryptedFile.getName() + ".pgp"); File encryptedResult = new File("encrypted.txt"); try (OutputStream out = new DataOutputStream(new FileOutputStream(encryptedFile)); FileInputStream publicKeyStream = new FileInputStream(publicKey)) { encryptFile(out, unencryptedFile.getPath(), readPublicKey(publicKeyStream), false, true); try (InputStream in = new FileInputStream(encryptedFile); OutputStream outResult = new FileOutputStream(encryptedResult); FileInputStream privateKeyStream = new FileInputStream(secretKey)) { // Decrypt the encrypted file decryptFile(in, outResult, privateKeyStream, passPhrase); } } // Check that the decrypted file matches the original unencrypted file try (BufferedReader reader1 = new BufferedReader(new FileReader(unencryptedFile)); BufferedReader reader2 = new BufferedReader(new FileReader(encryptedResult))) { String line1 = reader1.readLine(); String line2 = reader2.readLine(); while (line1 != null && line2 != null) { assertEquals(line1, line2); line1 = reader1.readLine(); line2 = reader2.readLine(); } assertNull(line1); assertNull(line2); } // Clean up the files unencryptedFile.delete(); encryptedFile.delete(); encryptedResult.delete(); }
求助
恳请帮忙排查该问题。
内容的提问来源于stack exchange,提问作者javaConsumtion
相关产品推荐
相关产品推荐

