【问题标题】:Algorithm HmacPBESHA256 not available算法 HmacPBESHA256 不可用
【发布时间】:2016-09-30 18:22:21
【问题描述】:

所以,我编写了一些代码来获取 PEM,通过 bouncycastle 将其添加到 PKCS 密钥库,然后使用 java crypto 将 PKCS 密钥库值导入 JKS 密钥库。

我发誓昨天我成功通过了单元测试并执行了这些步骤,但今天早上我开始点击这个

Caused by: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available
    at javax.crypto.Mac.getInstance(Mac.java:181) ~[na:1.8.0_60]
    at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2039) ~[na:1.8.0_65]

现在,总有可能在我身下发生了一些变化,但我不知道是什么。似乎我 用于该算法的任何提供者都已经消失了。

这是我的 java.security 文件 sn-p:

security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=sun.security.ec.SunEC
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=apple.security.AppleProvider

代码并不多。首先,我通过 bouncycastle 创建一个 PKCS 密钥库,添加一个 pem 并作为 PKCS12 保存到磁盘。然后通过 java crypto 导入,保存为 JKS。

   public KeystoreBuilder createJksFromPem(String pemPrivate, String pemPublic, String alias) throws Exception
    {
        Preconditions.checkState(StringUtils.isNotEmpty(pemPrivate), "pemPrivate must not be empty");
        Preconditions.checkState(StringUtils.isNotEmpty(pemPublic), "pemPublic must not be empty");
        Preconditions.checkState(StringUtils.isNotEmpty(alias), "alias must not be empty");

        String pkcsFilename = filename + ".pkcs";
        convertPemToPkcs(pemPrivate, pemPublic, pkcsFilename);

        importPkcsIntoJks(pkcsFilename);

        return this;
    }

    private void importPkcsIntoJks(String pkcsFilename) throws Exception
    {
        KeyStore pkcs = KeyStore.getInstance("PKCS12");
        File pkcsFile = new File(pkcsFilename);
        try (FileInputStream fis = new FileInputStream(pkcsFile))
        {
            pkcs.load(fis, password.toCharArray());
        }
        pkcsFile.delete();

        KeyStore jks = KeyStore.getInstance("JKS");
        jks.load(null);

        Enumeration<String> aliases = pkcs.aliases();
        while (aliases.hasMoreElements())
        {
            String alias = aliases.nextElement();
            if (!pkcs.isKeyEntry(alias))
            {
                continue;
            }
            Key key = pkcs.getKey(alias, password.toCharArray());
            Certificate[] chain = pkcs.getCertificateChain(alias);

            jks.setKeyEntry(alias, key, password.toCharArray(), chain);
        }

        persist(jks);
    }

    private void convertPemToPkcs(String pemPrivate, String pemPublic, String pkcsFilename) throws IOException, NoSuchAlgorithmException, OperatorCreationException, PKCSException, FileNotFoundException
    {
        Security.addProvider(new BouncyCastleProvider());

        X509CertificateHolder cert = (X509CertificateHolder) readObject(pemPublic);
        PEMKeyPair keyPair = (PEMKeyPair) readObject(pemPrivate);

        JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
        PKCS12SafeBagBuilder pkcs12BagBuilder = new PKCS12SafeBagBuilder(cert);
        pkcs12BagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString("Kafka SSL Certificate"));
        pkcs12BagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId, extUtils.createSubjectKeyIdentifier(keyPair.getPublicKeyInfo()));

        PKCS12PfxPduBuilder builder = new PKCS12PfxPduBuilder();

        builder.addData(pkcs12BagBuilder.build());

        builder.addEncryptedData(new JcePKCSPBEOutputEncryptorBuilder(PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC2_CBC).setProvider("BC").build(password.toCharArray()), pkcs12BagBuilder.build());

        PKCS12PfxPdu pfx = builder.build(new JcePKCS12MacCalculatorBuilder(NISTObjectIdentifiers.id_sha256), password.toCharArray());

        try (FileOutputStream fos = new FileOutputStream(new File(pkcsFilename)))
        {
            fos.write(pfx.getEncoded(ASN1Encoding.DL));
        }
    }

然后砰的一声炸了

pkcs.load(fis, password.toCharArray());

如您所见,BouncyCastleProvider 是显式添加的。有什么建议?

更新:感谢 dave_thompson_085 的建议。不敢相信我没有看到那个重载的方法,但解决方案是在调用 get Keystore.getInstance("PKCS12", "BC") 中指定提供程序。

【问题讨论】:

  • 互联网搜索显示this bug 可能相关。此外,我在任何地方都没有看到 Bouncy Castle 提供程序,也许这会有所帮助?
  • 编辑一些代码来重放这个问题会很有帮助。
  • 添加 BC 提供者不优先;您的堆栈跟踪确认您正在获取 SunJSSE 提供程序的实现。尝试使用KeyStore.getInstance("PKCS12","BC"),或者如果您想在位置 4 或以下位置危险地插入 BC 提供程序。或者像其他人一样使用 SHA1 在 PKCS12 上执行 PB-MAC - 您是已经将它用于 PBE。另外,在我看来,您正在对证书进行强力加密——为什么??
  • aaaaahhhhhh 修复了它,感谢 dave_thompson_085!!
  • @dave_thompson_085,您具体指的是 WRT 的“强加密”代码? 'addEncryptedData()' 调用?

标签: java security cryptography


【解决方案1】:

打开Android Studio,进入File &gt; Settings &gt; Build, Execution, Development &gt; Build Tools &gt; Gradle,然后将Gradle JDK改成jdk16,然后点击Sync Gradle。

您可以毫无错误地进入构建项目。

【讨论】:

  • 在 android studio 中使用 JDK 15 解决了这个问题。 JDK 16 对某些依赖项抛出错误。
  • 我用JDK16解决了这个问题。我的 React 应用 React 现在可以工作了。
【解决方案2】:

正如 dave_thompson_085 所指出的,我可以指定我希望将哪个提供程序用于密钥库。最初我没有意识到这一点,因为我错过了 getInstance() 重载。

总之,调用这个解决了我的问题:

KeyStore.getInstance("PKCS12","BC")

太容易了。

【讨论】:

    【解决方案3】:

    HmacPBESHA256 听起来像是解密文件后验证完整性的算法。您可以解密您的密钥库并再次加密,这可能不使用HmacPBESHA256


    就我而言,我使用 Windows 工具(即“Microsoft Strong Cryptographic Provider”)生成密钥。默认情况下,pfx 使用 Java 11 不支持的HmacPBESHA256

    解决方案是创建一个新的密钥库,但使用openssl。为此,我运行:

    openssl pkcs12 -in "your_keystore.pfx" -nodes | openssl pkcs12 -export -out "new_keystore.pfx"
    

    这适用于jarsign/apksign,通过提供new_keystore.pfx 作为密钥库。

    【讨论】:

      【解决方案4】:

      标准 java(SunJCE 提供者)starting from Java 12 也支持 HmacPBESHA256 算法。 我会这样使用它:

      //run with Java 12!
      public void test() throws NoSuchAlgorithmException {
          Provider provider = java.security.Security.getProvider("SunJCE");
          System.out.println(provider.getName());
          Mac m = Mac.getInstance("HmacPBESHA256",provider);
          System.out.println(m.getAlgorithm());
      }
      

      【讨论】:

      • 我用的是java 16版,但还是报错
      • 但是你看documentation是不是可以正确设置Provider?
      • 是的,那里提到了。但是这个提供者是什么以及在哪里设置它?
      猜你喜欢
      • 2021-10-16
      • 2021-07-29
      • 1970-01-01
      • 2021-08-10
      • 2011-02-20
      • 2011-02-11
      • 1970-01-01
      • 2014-03-12
      相关资源
      最近更新 更多