title: Trying to Sign data with KeyChainStore using Java
body: <p>I'm actually developing an app that allows users to sign with their smartcard. On Windows OS, I have this :</p>
  
  <pre><code>ArrayList&lt;String&gt; lstErrors = new ArrayList&lt;String&gt;();
  String AliasToUse = "test";
  String strToSign = "My Clean String";
  
  String strSigned = AccessController.doPrivileged(new PrivilegedAction&lt;String&gt;()
          {
              public String run()
              {
                  KeyStore ks = null;
                  ks = KeyStore.getInstance("Windows-MY");
                  ks.load(null, null);
  
                  try
                  {
                      Enumeration&lt;String&gt; en = ks.aliases();
  
                      if (en.hasMoreElements() == false)
                      {
                          lstErrors.add("No Certificate found");
                          return null;
                      }
  
                      ArrayList&lt;String&gt; lstAlias = Collections.list(en);
  
                      lstErrors.add(lstAlias.size() + " elements found");
  
                      for (String aliasKey : lstAlias)
                      {
  
                          if(!aliasKey.equalsIgnoreCase(AliasToUse))
                          {
                              continue;
                          }
  
                          Provider p = ks.getProvider();
  
                          Signature sig = Signature.getInstance("SHA256withRSA", p);
  
                          PrivateKey key = (PrivateKey) ks.getKey(aliasKey, "1234".toCharArray());
  
                          if (key == null)
                          {
                              lstErrors.add("The Private Key could not be instanciated");
                              continue;
                          } 
  
                          sig.initSign(key);
                          String strBase64Decoded = Base64Coder.decodeString(strToSign);
                          byte[] btToSign = strBase64Decoded.getBytes(Charset.forName("UTF-8"));
                          sig.update(btToSign);
                          byte[] res = sig.sign();
  
                          return Base64Coder.encodeBase64String(res);
                      }
  
                  } catch (Exception e)
                  {
                      lstErrors.add("Error signing : " + e.getMessage());
                      return null;
                  }
  
                  return null;
              }
          }
  </code></pre>
  
  <p>This code works fine, no problem. When I try to do the same with Apple, I'm trying this :</p>
  
  <pre><code>ks = KeyStore.getInstance("KeyChainStore");
  </code></pre>
  
  <p>This allows me to get all the certificates but when I try to sign my data, I get the following error :</p>
  
  <blockquote>
    <p>no such algorithm: SHA256WithRSA for provider Apple</p>
  </blockquote>
  
  <p>It happens on the following line :</p>
  
  <pre><code>Signature sig = Signature.getInstance("SHA256withRSA", p);
  </code></pre>
  
  <p>I tried "SHA-256" or even "SHA-1" but the error still remains.</p>
  
  <p>How can I use the KeyChainStore to sign like I do in Windows Certificate Store ?</p>
  
  <p>Thanks in advance.</p>
  
  <h2>Addendum</h2>
  
  <p>I tried another method to gather more informations about each alias on my KeyChainStore, and know if the entry contains a certificate and/or a private key :</p>
  
  <pre><code>public void GetInformationsFromKeyChainStore() {
  
          AccessController.doPrivileged(new PrivilegedAction&lt;Boolean&gt;() {
              public Boolean run() {
  
                  try {
                      KeyStore keyStore = KeyStore.getInstance("KeychainStore",
                              "Apple");
                      keyStore.load(null, null);
  
                      System.out
                              .println("List of the aliases present in the keystore ("
                                      + keyStore.getType() + ")");
                      Enumeration&lt;String&gt; aliases = keyStore.aliases();
  
                      ArrayList&lt;String&gt; lstAlias = Collections.list(aliases);
  
                      for (String alias : lstAlias) {
  
                          System.out.println(" - Alias: " + alias);
                          System.out.println("     isKeyEntry? "
                                  + keyStore.isKeyEntry(alias));
                          System.out.println("     isCertificateEntry?"
                                  + keyStore.isCertificateEntry(alias));
                          if (keyStore.isKeyEntry(alias)) {
                              try {
                                  PrivateKey key = (PrivateKey) keyStore.getKey(
                                          alias, "-".toCharArray());
                                  System.out
                                          .println("    Key loaded successfully. Type: "
                                                  + key.getFormat());
                              } catch (RuntimeException e) {
                                  System.out.println("    Key failed to load ("
                                          + e.getMessage() + ")");
                              }
                              Certificate certificate = keyStore
                                      .getCertificate(alias);
                              String subject = "";
                              if ((certificate != null)
                                      &amp;&amp; (certificate instanceof X509Certificate)) {
                                  subject = ((X509Certificate) certificate)
                                          .getSubjectX500Principal().getName();
                              }
                              System.out.println("  Does getCertificate work on this key entry? "
                                      + ((keyStore.getCertificate(alias) != null) ? "Yes "
                                              + subject
                                              : "No"));
                          }
                          if (keyStore.isCertificateEntry(alias)) {
                              Certificate certificate = keyStore
                                      .getCertificate(alias);
  
                              if (certificate instanceof X509Certificate) {
                                  X509Certificate x509certificate = (X509Certificate) certificate;
                                  System.out.println("    Subject DN: "
                                          + x509certificate
                                                  .getSubjectX500Principal()
                                                  .getName());
                              } else {
                                  System.out
                                          .println("    Unknown format certificate.");
                              }
                              System.out
                                      .println("  Does getKey work on this certificate entry as well? "
                                              + (keyStore.getKey(alias,
                                                      "-".toCharArray()) != null));
  
                          }
                      }
  
                  } catch (Exception e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                      return false;
                  }
                  return true;
  
              }
          });
  
      }
  </code></pre>
  
  <p>But even this method call, all my entries seem to be certificates and don't contain any private key.</p>
  
  <p>The problem is that for some certificates, there is a private key (I can also view it from my KeyChainStore).</p>