我正在尝试使用 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 解密时不会提示输入原始数据文件来验证签名?
不是完整的答案,因为我没有时间重写你的代码,但是:
与 PKCS7/CMS/SMIME 不同,其中嵌入式(也称为封装)签名包含 SignedData 结构中的数据,在 PGP 中,(非分离)签名消息只是一系列数据包:
“One-Pass Signature”数据包,宣布要使用的算法
数据,通常作为“文字数据”数据包,但也可以选择是“压缩数据”数据包包含“文字数据”
一个“签名”数据包,包含(不出意外)数据的签名
rfc4880 11.3。从技术上讲,还定义了一种旧格式,它不使用“One-Pass”数据包,并且在数据之前有签名数据包,但实际上已经过时了。 相比之下,您的代码生成的签名数据包本身是一个独立的签名,根据 11.4(上述链接下一页)。
要在 BCPG 中生成“嵌入”签名消息,您必须
以获取工作示例(在我的答案中更正后)或https://github.com/bcgit/bc-java/blob/main/pg/src/main /java/org/bouncycastle/openpgp/examples/SignedFileProcessor.java . 当您(仅)在 PGP 中加密数据时,您必须首先将其嵌入到文字数据包中,或更常见(通常是默认)压缩/文字数据包中,但是当您签名然后加密时,签名消息已
已经一条 PGP 消息,并“直接”馈送到加密中,或者(再次)更常见地馈送到压缩到加密中。我不必为该部分提供良好的参考。