如何使用 bouncyCastle 在 Java 中编写嵌入式 pgp 签名?

问题描述 投票:0回答:1

我正在尝试使用 embedded 签名在 pgp 中签署加密消息。

我可以使用下面的代码创建一个独立的签名,使用 bouncyCastle 的 pgp 库进行签名和加密:

public static byte[] pgpSign(PGPPrivateKey signingKey, byte[] data) throws PGPException, IOException {
        PGPSignatureGenerator sGen = new PGPSignatureGenerator(
                new BcPGPContentSignerBuilder(signingKey.getPublicKeyPacket().getAlgorithm(), SHA256));
        sGen.init(PGPSignature.BINARY_DOCUMENT, signingKey);
        sGen.update(data);
        PGPSignature signature = sGen.generate();
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        signature.encode(output);
        output.close();
        return output.toByteArray();
}

public static byte[] pgpSignAndEncrypt_Detached(PGPPublicKey encryptionKey, PGPPrivateKey signingKey, byte[] data) throws IOException, PGPException, ClassCastException{
        PGPEncryptedDataGenerator encryptionGenerator = new PGPEncryptedDataGenerator(
                new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256)
                        .setSecureRandom(new SecureRandom())
                        .setWithIntegrityPacket(true)
        );
        encryptionGenerator.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(encryptionKey));
        ByteArrayOutputStream encryptedStream = new ByteArrayOutputStream();


        OutputStream literalDataStream = encryptionGenerator.open(encryptedStream, new byte[1048576]);
        OutputStream rawStream = new PGPLiteralDataGenerator().open(literalDataStream, PGPLiteralData.BINARY, "", new Date(), new byte[1048576]);
        rawStream.write(data);
        rawStream.close();
        literalDataStream.close();
        encryptedStream.write(pgpSign(signingKey, data));
        encryptedStream.close();
        return encryptedStream.toByteArray();
}

我本来希望获得嵌入的签名,但是,当尝试使用 gpg 解密时,我得到以下输出:

gpg2 --解密 testEmbedded.pgp

gpg:使用 3072 位 RSA 密钥加密,ID 9505FCA2AEF76A5B,创建于 2023-06-19

“userId(testKeypair)mailto:[email protected]

世界你好

分离签名。

请输入数据文件名称:

分离签名和嵌入签名有什么区别?毕竟,这个“独立”签名与加密消息位于同一个 .pgp 文件中。 如何创建嵌入签名,以便在使用 gpg 解密时不会提示输入原始数据文件来验证签名?

java bouncycastle pgp openpgp
1个回答
0
投票

不是完整的答案,因为我没有时间重写你的代码,但是:

与 PKCS7/CMS/SMIME 不同,其中嵌入式(也称为封装)签名包含 SignedData 结构中的数据,在 PGP 中,(非分离)签名消息只是一系列数据包:

  1. “One-Pass Signature”数据包,宣布要使用的算法

  2. 数据,通常作为“文字数据”数据包,但也可以选择是“压缩数据”数据包包含“文字数据”

  3. 一个“签名”数据包,包含(不出意外)数据的签名

参见

rfc4880 11.3。从技术上讲,还定义了一种旧格式,它不使用“One-Pass”数据包,并且在数据之前有签名数据包,但实际上已经过时了。 相比之下,您的代码生成的签名数据包本身是一个独立的签名,根据 11.4(上述链接下一页)。

要在 BCPG 中生成“嵌入”签名消息,您必须

    生成 One-Pass 数据包
  1. 将数据写入文字数据包(或压缩/文字数据包)并使用该数据更新签名;一起执行这些操作是最方便的,尽管单独执行它们就足够了,只要两者实际上都已完成并且一致
  2. 生成签名包
  3. 请参阅
如何在 JAVA 中签署和验证文件

以获取工作示例(在我的答案中更正后)或https://github.com/bcgit/bc-java/blob/main/pg/src/main /java/org/bouncycastle/openpgp/examples/SignedFileProcessor.java . 当您(仅)在 PGP 中加密数据时,您必须首先将其嵌入到文字数据包中,或更常见(通常是默认)压缩/文字数据包中,但是当您签名然后加密时,签名消息已

已经

一条 PGP 消息,并“直接”馈送到加密中,或者(再次)更常见地馈送到压缩到加密中。我不必为该部分提供良好的参考。

© www.soinside.com 2019 - 2024. All rights reserved.