为什么 Java KeyStore 在加载 OpenPGP 密钥时失败?

Why does the Java KeyStore fail at loading an OpenPGP key?

我愿意花一些时间为桌面 Java 应用程序开发另一个许可证管理器。环顾四周后,我发现 JCPUID by Iakin that is free to use and should work at most operating systems with native libs that I found here.

我的想法是做两个模块:将显示带有 CPU ID 和验证文本字段的弹出窗口 window 的主应用程序和密钥生成器应用程序。用户将 CPU ID 传递给密钥生成器所有者,密钥生成器所有者将 return 验证码(使用密钥生成器生成)传递给用户。用户提交正确的验证码后,将在文件系统中创建包含该验证码的许可证文件。每次应用程序启动时,它都会检查该文件的存在和正确性,然后加载主应用程序屏幕。

关于代码验证,我认为最好的选择是使用非对称加密,尤其是 RSA。 public 密钥将内置到应用程序中,秘密将内置到密钥生成器中。因此 CPUID 将传递给密钥生成器所有者,然后使用 RSA 进行签名。该签名将被传回给用户,用户将使用内置的 public 密钥验证其有效性。

我使用 Kleopatra 和 gpg Linux 命令行工具本身生成了 gpg 密钥对。然后我尝试使用这种方法签名:

    private byte[] createSignature(byte[] file) {
    byte[] signature = null;

    try {
        java.security.KeyStore keyStoreFile = java.security.KeyStore
                .getInstance("PKCS12");
        keyStoreFile.load(getClass().getClassLoader().getResourceAsStream("/secret.asc"),
        "******".toCharArray());

        PrivateKey privateKey = (PrivateKey) keyStoreFile.getKey(
                "My Name Here", "******".toCharArray());

        Signature dsa = Signature.getInstance("SHA1withRSA");
        dsa.initSign(privateKey);
        dsa.update(file, 0, file.length);
        signature = dsa.sign();

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return signature;
}

但是 privateKey 初始化抛出异常:

java.security.InvalidKeyException: Key must not be null

我猜是因为这里的实例格式错误:

java.security.KeyStore keyStoreFile = java.security.KeyStore
            .getInstance("PKCS12");

我想知道:

  1. 这种方法到底有多好?

  2. 不同的 OpenPGP 密钥格式之间存在什么区别,在这种情况下哪种格式最好?如何知道现有OpenPGP文件的格式?

Java 加密框架不支持 OpenPGP。 X.509 密钥,例如 PKCS12 格式,与 OpenPGP 不兼容——尽管它们(主要)依赖于相同的加密算法。

要么使用 X.509 证书(您也可以为此目的创建自己的 CA),要么依赖 Java 的 OpenPGP 实现。在开源库方面,您可以在本机 Java 实现 BouncyCastle (MIT license), or interface GnuPG (GPL) through the Java GPGME binding (LGPL) 之间进行选择。

BouncyCastle 可能是更好的选择,因为您需要做的就是添加另一个 Java 库,而不是在系统中安装另一个软件。