【发布时间】:2020-12-30 07:43:54
【问题描述】:
我正在尝试使用 bouncy-gpg 库和 BouncyCastle 在我的 Java 程序中进行 PGP 加密。我不断得到以下NPE。
我们有一个在 Linux 机器上调用 gpg 的 shell 脚本,我想将该逻辑移动到 Windows 上的 Java 应用程序中。我从 Linux 上的密钥环中导出了公钥并尝试在 Windows 上使用它,但我总是收到以下错误。我尝试了各种不同密钥、格式和 API 选项的变体,但我无法使用这一个密钥进行加密。使用我自己生成的密钥对可以正常工作。
/**
* Encypt the output file using gpg
*/
public void encryptFile() {
Path sourceFile = Paths.get(this.filePath());
Path destFile = Paths.get(this.encryptedFilePath());
try {
BouncyGPG.registerProvider();
int bufferSize = 8 * 1024;
InMemoryKeyring keyringConfig = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
try {
keyringConfig.addPublicKey(Files.readAllBytes(Paths.get("c:/path/to/my/exported.key"));
} catch ( Exception e ) {
throw new RuntimeException(e);
}
try (
OutputStream fileOutput = Files.newOutputStream(destFile);
BufferedOutputStream bufferedOut = new BufferedOutputStream(fileOutput, bufferSize);
OutputStream outputStream = BouncyGPG
.encryptToStream()
.withConfig(keyringConfig)
.withStrongAlgorithms()
.toRecipient(recipient)
.andDoNotSign()
.binaryOutput()
.andWriteTo(bufferedOut);
InputStream is = Files.newInputStream(sourceFile)
) {
Streams.pipeAll(is, outputStream);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
这里是异常的堆栈跟踪:
Caused by: java.lang.NullPointerException
at name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.generation.KeyFlag.extractPublicKeyFlags(KeyFlag.java:106)
at name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.Rfc4880KeySelectionStrategy.isEncryptionKey(Rfc4880KeySelectionStrategy.java:228)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:174)
at java.util.ArrayList$Itr.forEachRemaining(ArrayList.java:891)
at java.util.Collections$UnmodifiableCollection$1.forEachRemaining(Collections.java:1049)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270)
at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1548)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:479)
at name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.Rfc4880KeySelectionStrategy.selectPublicKey(Rfc4880KeySelectionStrategy.java:156)
at name.neuhalfen.projects.crypto.bouncycastle.openpgp.BuildEncryptionOutputStreamAPI$WithAlgorithmSuiteImpl$ToImpl.extractValidKey(BuildEncryptionOutputStreamAPI.java:411)
at name.neuhalfen.projects.crypto.bouncycastle.openpgp.BuildEncryptionOutputStreamAPI$WithAlgorithmSuiteImpl$ToImpl.toRecipient(BuildEncryptionOutputStreamAPI.java:431) ...
以及发生 NPE 的 bouncy-gpg 中的代码块。 hashedSubPackets 变量为空:
while (directKeySignatures.hasNext()) {
final PGPSignature signature = directKeySignatures.next();
final PGPSignatureSubpacketVector hashedSubPackets = signature.getHashedSubPackets();
final int keyFlags = hashedSubPackets.getKeyFlags(); // <- NPE HERE
aggregatedKeyFlags |= keyFlags;
}
非常感谢您的任何帮助。
【问题讨论】:
-
如果您可以编辑您的帖子并附加一个示例公共和私有 PGP 密钥对以使用您不起作用的密钥运行测试,这可能是个好主意。
-
该代码块不在“BouncyCastle”中。正如您的堆栈跟踪所示,它是 Jens Neuhalfen 的 bouncy-gpg 代码的一部分,该代码最近已更改以完全解决此问题。请参阅github.com/neuhalje/bouncy-gpg/blame/master/src/main/java/name/… 并将鼠标悬停在标题(或责备项)“合并github.com/ispringer/bouncy-gpg 的分支'issue-48'”上。 @MichaelFehr:加密只需要公钥,这对于公开发布来说不是什么问题
-
@dave_thompson_085:你说得对,关于安全问题,我要求提供 sample 密钥对 :-)
-
非常感谢您的快速和翔实的答复。我确实看到这是 bouncy-gpg 包中的一个错误,它已修复但从未发布到生产存储库。参见参考github.com/neuhalje/bouncy-gpg/issues/48。在他们发布修复之前,我将使用提交中所示的修复在我的项目中实现和覆盖 KeyFlag 类。
-
@dave_thompson_085 我编辑了原始帖子和标题以反映该错误在 bouncy-gpg 库中,而不是在 BouncyCastle 中。
标签: java bouncycastle gnupg pgp