You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 20:27:55