title: Algorithm HmacPBESHA256 not available
body: <p>So, I have written some code to take a PEM, add it to a PKCS keystore via bouncycastle, and then use java crypto to import the PKCS keystore value into a JKS keystore.</p>
  
  <p>I swear that yesterday I had a unit test pass successfully having executed these steps, but this morning I started hitting this</p>
  
  <pre><code>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]
  </code></pre>
  
  <p>Now, it's always possible something changed underneath me but I cannot figure out what it was.  It seems whatever provider I <em>was</em> using for that algorithm has since disappeared. </p>
  
  <p>here's my java.security file snippet:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>There's not a whole lot to the code.  First I create a PKCS keystore via bouncycastle, adding a pem and saving to disk as PKCS12. Then import via java crypto, saving back out as JKS.</p>
  
  <pre><code>   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&lt;String&gt; 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));
          }
      }
  </code></pre>
  
  <p>and boom it blows up on </p>
  
  <pre><code>pkcs.load(fis, password.toCharArray());
  </code></pre>
  
  <p>As you can see, the BouncyCastleProvider was added explicitly. Any suggestions? </p>
  
  <p>UPDATE: Thanks dave_thompson_085 for the suggestion.  Can't believe I didn't see that overloaded method, but the solution was to specify the provider in the call get Keystore.getInstance("PKCS12", "BC").</p>