This discussion is archived
1 2 Previous Next 26 Replies Latest reply: Oct 10, 2012 7:31 PM by EJP RSS

PKCS11 & javax.net.ssl.keyStoreAlias

843811 Newbie
Currently Being Moderated
Hello,

using JDK 1.5 I want to do a certificate authentication against LDAP (Sun Java System Directory Server).
On my smart card I've more than one (different kind of) certificates. But only a certain one is for login purposes, the others are for signing and stuff.
With the java keytool I can read out all certificates and even a certain one by using the alias.

With this piece of code it doesn't work.
With the SSL debug turned on, I can see that always the 1. certificate (maybe as default) is used and that the connection is refused.

h6.
What is the story behind 'javax.net.ssl.keyStoreAlias' and how can I use a certain certificate for my bind?
Hashtable<String, Object> env = new Hashtable<String, Object>();
/* THE LDAP STUFF */
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, PROVIDER_URL_SSL);
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put("java.naming.ldap.version", "3");
env.put("java.naming.ldap.factory.socket", "javax.net.ssl.SSLSocketFactory");
env.put(Context.SECURITY_AUTHENTICATION, "EXTERNAL");

/* THE SMARTCARD */
System.setProperty("javax.net.ssl.keyStore", "NONE");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS11");
System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11-MyCard");
System.setProperty("javax.net.ssl.keyStoreAlias", "Windows 2000 Logon-Zertifikat");

myCtx = new InitialDirContext(env);
Thread-0, WRITE: TLSv1 Handshake, length = 32
Thread-0, waiting for close_notify or alert: state 1
Thread-0, Exception while waiting for close java.net.SocketException: Software caused connection abort: recv failed
Thread-0, handling exception: java.net.SocketException: Software caused connection abort: recv failed
main, handling exception: java.net.SocketException: Software caused connection abort: recv failed
main, SEND TLSv1 ALERT:  fatal, description = unexpected_message
main, WRITE: TLSv1 Alert, length = 18
main, Exception sending alert: java.net.SocketException: Software caused connection abort: socket write error
main, called closeSocket()
I can do user/pwd authentication.
I can do SSL.
The root and the issuer certs are in my cacerts file.
The program runs and then my SmartCardReader beeps an let me enter my pin.
So the environment seems to fit, but not the choosen cert.

Thanks for your help!

Best regards
  • 1. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Hi,

    I'm back with new information.

    On my smart card are 3 certs, as said before.
    All 3 certs are in slot1.
    After checking the key usage info, I see now the following.
    Cert 1: (DigitalSignature, Non_repudiation)
    Cert 2: (DigitalSignature, Non_repudiation, Key_Encipherment, Key_Agreement) = 'Windows 2000 Logon-Zertifikat'
    Cert 3: (Key_Encipherment, Data_Encipherment)
    With Jdk 1.5 Cert +3+ is used, that results in *'Software caused connection abort: recv failed'*
    With Jdk 1.6 Cert +1+ is used, that results in a sucessfull SSL bind !

    Why is it working with JDK 1.6? Is JDK 1.6 able to find a cert with the right key usage?
    Or is it just working by accident?

    How can I determine a certain cert during a LDAP bind?
    Why is 'javax.net.ssl.keyStoreAlias' still ignored.

    Is it true that the logon cert must be in slot 0?

    I hope anyone can help me with theses additional info.

    regards
  • 2. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    NX-01,

    From reading other postings on the web with the same issue, some of them also stated that it only worked with JDK 1.6, perhaps it is a new feature.

    I did have a question though regarding your code.
    I am trying to do the exact same thing, but receiving different errors. I think I am confused as to what to put for the following values:
    --keyStoreProvider
    --keyStoreAlias

    This is what I have so far:
    ...
    //LDAP            
    env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");            
    env.put(Context.PROVIDER_URL,ldapURL);            
    env.put(Context.SECURITY_PROTOCOL, "ssl");            
    env.put("java.naming.ldap.version", "3");            
    env.put("java.naming.ldap.factory.socket", "javax.net.ssl.SSLSocketFactory");            
    env.put(Context.SECURITY_AUTHENTICATION, "EXTERNAL");                       
    
     //SMARTCARD            
    System.setProperty("javax.net.ssl.keyStore", "NONE");            
    System.setProperty("javax.net.ssl.keyStoreType", "PKCS11");            
    System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11");            
    System.setProperty("javax.net.ssl.keyStoreAlias", "Windows 2000 Logon-Zertifikat");           
     
     //Create the initial directory context            
    InitialLdapContext ctx =  new InitialLdapContext(env,null);
    ...
    But I receive the following error:
    Problem searching directory: javax.naming.CommunicationException: my.company.com:636 [Root exception is java.net.SocketException: Default SSL context init failed: no such provider: SunPKCS11]
    Any suggestions on how you overcame this, and what values should I use for keyStoreProvider and keyStoreAlias?

    thanks,

    SK
  • 3. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Hello SK,

    today I received an anwser from SUN.
    This is a known bug and it is only fixed in Java 6!
    Maybe it will be fixed for Java 5 someday.

    Now to your questions:
    Because a SCR (SmardCardReader) is barely a supported provider by default, you have to add this (your) provider to the JRE.

    In \jdk1.6.0\jre\lib\security you can find the java.security file. There is a section with 9 default/known providers.
    There you have to add such a line:
    security.provider.10=sun.security.pkcs11.SunPKCS11 E:/pkcs11.cfg
    Important : No backslashes in the path!

    This config file (pkcs11.cfg) must contain the path to your provider lib (DLL). The SCR manufacturer.

    e.g.
    name=MyCard
    library=C:\WINDOWS\system32\MyProvider.dll
    About the keyStoreAlias I'm not so sure that this is a valid/useful parameter at all.
    As described I've 3 certs on my smard card, but even in the working environment with Java 6, a different cert is used then I wanted.
    I hope I get an answer from SUN which criteria in Java 6 is responsible for the choosen cert.

    If you've do work in this crypto area during the next weeks, as I do, we should stay in contact.

    Best regards NX-01
  • 4. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Hello NX-01,

    Thanks for the reply. I agree, we should stay in contact. I clicked on your account though, no email address listed, so we'll have to contact via the forums.

    Anyway, on to the situation, I have questions on your post.

    First, I found the java.security file, and added the 10th line as you stated and now have these entries:
    security.provider.1=sun.security.provider.Sun
    security.provider.2=sun.security.rsa.SunRsaSign
    security.provider.3=com.sun.net.ssl.internal.ssl.Provider
    security.provider.4=com.sun.crypto.provider.SunJCE
    security.provider.5=sun.security.jgss.SunProvider
    security.provider.6=com.sun.security.sasl.Provider
    security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    security.provider.8=sun.security.smartcardio.SunPCSC
    security.provider.9=sun.security.mscapi.SunMSCAPI
    security.provider.10=sun.security.pkcs11.SunPKCS11 C:/Program Files/Java/jre1.6.0_03/lib/security/pkcs11.cfg
    I put the cfg in the same directory as the java.security file.

    I created the pkcs11.cfg file that now says this:
    name=ActiveClientProvider
    library=C:\WINDOWS\system32\acpkcs211.dll
    Which is where I have two questions on the cfg file.
    1. Is "name" anything I want it to be, I chose ActiveClientProvider because we are using ActiveIdentities' ActiveClient. And if so, do I refer to it as my keyStoreProvider like this:
    System.setProperty("javax.net.ssl.keyStoreProvider", "ActiveClientProvider");
    2. Also, you indicated no backslashes, but in the example gave:
    library=C:\WINDOWS\system32\MyProvider.dll
    So did you mean no backslashes in the cfg file "library address", or no backslashes in the java.security file "path to cfg file"?

    Sorry for all the questions, just trying to eliminate as many errors as I can before I test this out.

    thanks,

    SK


  • 5. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Hello again NX-01,

    Did some more testing, and I came across an error, which of course led me to some other things that I was hoping you could help me out with.

    Here is the error:
    java.security.ProviderException: Initialization failed
         sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:340)
         sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:86)
         tnosc.searchexternals.returnStuff(searchexternals.java:38)
         org.apache.jsp.test_jsp._jspService(org.apache.jsp.test_jsp:76)
         org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
         javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
         org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:332)
         org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
         org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
         javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
    The tnosc.searchexternals.returnStuff(searchexternals.java:38) is my package.class.method, line 37 and 38 read:
    String configName = "C:/Program Files/Java/jre1.6.0_03/lib/security/pkcs11.cfg";
    sun.security.pkcs11.SunPKCS11 p = new sun.security.pkcs11.SunPKCS11(configName);
    And of course, my cfg file reads the same as mentioned previously.

    So it cannot initialize my library to my provider is what it sounds like. This means it cannot find it, or something else? The path is correct. But after some googling around, I did find 2 other people with the same error and environment. But each with different explanations.

    [Explanation 1|http://www.mail-archive.com/mozilla-crypto@mozilla.org/msg08048.html] seems to indicate I'm missing parameters on the config file.
    [Explanation 2|http://archive.netbsd.se/?ml=mozilla-crypto&a=2007-07&t=4754859] seems to say that it is a parsing issue with the use of backslash in the config and the security file and possibly the class file.

    I changed the java.security file to use a single backslash "\" between directories to match the config file which did the same. The class file I tried both forward slash "/" and double backslash "\\" since the path to the config file was just a string. Both gave same error mentioned above.

    Anyway, still scratching my head here, any help would be appreciated.

    thanks,

    SK

    Edited by: scryptkiddy on Apr 7, 2008 6:41 PM

    Edited by: scryptkiddy on Apr 7, 2008 6:43 PM
  • 6. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Hello,

    here some probably usefull answers:

    1) The value for the keyStoreProvider contains 2 elements.
    The Java Class Name from the provider entry in the java.security file and the self choosen name in the selfmade cfg file.
    security.provider.10=sun.security.pkcs11.*SunPKCS11* E:/pkcs11.cfg
    name=*MyCard*
    System.setProperty("javax.net.ssl.keyStoreProvider", "*SunPKCS11*-*MyCard*");
    2) Path & backslashes

    no backslashes in the java.security file "path to cfg file.
    backslashes in the cfg file "library address" are ok.

    Maybe there more ways to get everything running, I can only tell my configuration.

    best regards
  • 7. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Now I've a question.

    What are you trying to do with this code?
    String configName = "C:/Program Files/Java/jre1.6.0_03/lib/security/pkcs11.cfg";
    sun.security.pkcs11.SunPKCS11 p = new sun.security.pkcs11.SunPKCS11(configName);
    Are you trying to read out your smartcard or are you trying to do some ldap authentication stuff?
    Because in either cases you need different things.

    best regards
  • 8. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Odd, I have a watch on this topic, but did not get emailed of a new posting...

    Anyway, for your first post, thanks that makes sense, I do believe backslashes in the cfg file are okay as well, and I do have
    the keyStoreProvider to now say "SunPKCS11-ActiveClientProvider" vice just "ActiveClientProvider", thanks!

    Still getting errors:
    ...
     java.security.ProviderException: slotListIndex is 0 *but token only has 0 slots*
    ...
    Which means "I can't see any smartcards". But I don't want it to look for smartcard slots, I want it to look at the certificate that the user presented to the website when they were prompted (from the server.xml where I have on my connector "clientauth=true").



    For your other post, I was trying to see if dynamic loading (in class file as you saw) of a provider would be any different
    (in operation or error generation) than static (config file referenced in java.security).

    Didn't work out, same error as above. =)

    Help, lol

    SK
  • 9. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Before I started with the real stuff, I just tried to get generally access to the SCR.
    Using Java 6 and the above mentioned extensions in java.security.
    The log statements are from log4j.
    If you don't use log4j, replace it with system.out.println()

    Try this little to code :
        public void readKeyStoreFromSmartCard() throws
                GeneralSecurityException, IOException {
            String alias = null;
            KeyStore lks = KeyStore.getInstance("PKCS11");
            lks.load(null,null);
            Provider p = lks.getProvider();
            log.info("--------------------------------------------------------");
            log.info("Provider   : " + p.getName());
            log.info("Prov.Vers. : " + p.getVersion());
            log.info("KS Type    : " + lks.getType());
            log.info("KS DefType : " + lks.getDefaultType());
    
            Enumeration<String> al = lks.aliases();
            while (al.hasMoreElements()) {
                alias = al.nextElement();
                log.info("--------------------------------------------------------");
                if (lks.containsAlias(alias)) {
                    log.info("Alias exists : '" + alias + "'");
                    X509Certificate cert = (X509Certificate) lks.getCertificate(alias);
                    //log.info("Certificate  : '" + cert.toString() + "'");
                    log.info("Version      : '" + cert.getVersion() + "'");
                    log.info("SerialNumber : '" + cert.getSerialNumber() + "'");
                    log.info("SigAlgName   : '" + cert.getSigAlgName() + "'");
                    log.info("NotBefore    : '" + cert.getNotBefore().toString() + "'");
                    log.info("NotAfter     : '" + cert.getNotAfter().toString() + "'");
                    log.info("TBS          : '" + cert.getTBSCertificate().toString() + "'");
                } else {
                    log.info("Alias doesn't exists : '" + alias + "'");
                }
            }
        }
    Hope it helps.

    Best regards
  • 10. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Hey NX-01,

    Thanks for the reply!

    Not quite sure how to run this code of yours though. As a class, or a method within a main, or instantiating it from a servlet?
    Maybe I'm just tired and can't think straight, haha =)

    SK
  • 11. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    NX-01,

    I tried this in my Eclipse Project:
    import java.security.KeyStore;
    import java.security.Provider;
    import java.util.*;
    import java.security.cert.X509Certificate;
    
    public class readKeyStoreFromSmartCard {
    
         /**
          * @param args
          */
         public static void main(String[] args) {
              
              try {
                   readIt();
              }
              catch (Exception e) {
                   e.printStackTrace();
              }
    
         }     
              public static void readIt() throws Exception {
                  String alias = null;
                  KeyStore lks = KeyStore.getInstance("PKCS11");
                  lks.load(null,null);
                  Provider p = lks.getProvider();
                  System.out.println("--------------------------------------------------------");
                  System.out.println("Provider   : " + p.getName());
                  System.out.println("Prov.Vers. : " + p.getVersion());
                  System.out.println("KS Type    : " + lks.getType());
                  System.out.println("KS DefType : " + lks.getDefaultType());
              
                  Enumeration <String> al = lks.aliases();
                  while (al.hasMoreElements()) {
                      alias = al.nextElement();
                      System.out.println("--------------------------------------------------------");
                      if (lks.containsAlias(alias)) {
                          System.out.println("Alias exists : '" + alias + "'");
                          X509Certificate cert = (X509Certificate) lks.getCertificate(alias);
                          System.out.println("Certificate  : '" + cert.toString() + "'");
                          System.out.println("Version      : '" + cert.getVersion() + "'");
                          System.out.println("SerialNumber : '" + cert.getSerialNumber() + "'");
                          System.out.println("SigAlgName   : '" + cert.getSigAlgName() + "'");
                          System.out.println("NotBefore    : '" + cert.getNotBefore().toString() + "'");
                          System.out.println("NotAfter     : '" + cert.getNotAfter().toString() + "'");
                          System.out.println("TBS          : '" + cert.getTBSCertificate().toString() + "'");
                      } else {
                          System.out.println("Alias doesn't exists : '" + alias + "'");
                      }
                  }
              }
    
    
    }
    java.security.KeyStoreException: PKCS11 not found
         at java.security.KeyStore.getInstance(Unknown Source)
         at tnosc.readKeyStoreFromSmartCard.readIt(readKeyStoreFromSmartCard.java:27)
         at tnosc.readKeyStoreFromSmartCard.main(readKeyStoreFromSmartCard.java:17)
    Caused by: java.security.NoSuchAlgorithmException: PKCS11 KeyStore not available
         at sun.security.jca.GetInstance.getInstance(Unknown Source)
         at java.security.Security.getImpl(Unknown Source)
    and received the following error when I executed it:
    I would assume it means it cannot find the provider dll, not sure.

    SK
  • 12. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Hello SK,

    as I said keep the first samples as easy as possible.
    And you did it with the old simple console app.
    It will get much more complex if you start with wep apps or webstart as I do right now.

    So I did some tests about reasons for failure.
    And your problem is not about finding the dll.
    This would cause other errors as you can see below.

    There could be two reasons IMHO.
    1. Your smart card is not inserted correctly or the SCR is not plugged/installed as it should be.
    +(Don't beat me for that issue, but I inserted my SC wrong at the very first beginning)+
    2. You are using the wrong java.security file. One that misses the additional provider line.

    Maybe there is a 3rd reason, but I could only force this error with the 2 cases.

    Otherwise one of the below errors would appear
    --------------------------------------------------------------------------------------
    #security.provider.10=sun.security.pkcs11.SunPKCS11 E:/pkcs11.cfg
    --> java.security.KeyStoreException: PKCS11 not found
    --> Caused by: java.security.NoSuchAlgorithmException: PKCS11 KeyStore not available
    --------------------------------------------------------------------------------------
    ### Card not inserted or wrong side down or flipped
    --> java.security.KeyStoreException: PKCS11 not found
    --> Caused by: java.security.NoSuchAlgorithmException: PKCS11 KeyStore not available
    --------------------------------------------------------------------------------------
    security.provider.10=sun.security.pkcs11.SunPKCS11 
    --> java.security.ProviderException: SunPKCS11 requires configuration file argument
    --------------------------------------------------------------------------------------
    library=C:\WINDOWS\system32\kpkcs11hashxxxxxxx.dll
    --> java.security.ProviderException: Library C:\WINDOWS\system32\kpkcs11hashxxxxxxx.dll does not exist
    --------------------------------------------------------------------------------------
    #library=C:\WINDOWS\system32\kpkcs11hash.dll
    --> java.security.ProviderException: Error parsing configuration
    --------------------------------------------------------------------------------------
    security.provider.10=sun.security.pkcs11.SunPKCS11 E:/pkcs11xxxx.cfg
    --> java.security.ProviderException: Error parsing configuration
    --------------------------------------------------------------------------------------
    Do you have any testing tool from you SCR manufacturer to read the SC in SCR?
    Just to get sure that the basic installation is working properly.

    If this is the case, then you focus on the java staff.

    By the way which java version we are talking about?
    There are rumors about problems with low underscore versions of Java 5, besides the current little bug.

    Do you have access to the SC with the java keytool?

    Best regards
    NX-01
  • 13. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Hey NX,

    Thanks for the reply, its nice to have someone who has done this before give a "guided tour" of how this works!

    Now to the nitty gritty...

    My current configuration is I have my Eclipse IDE on my local workstation where I develop using jdk 1.6.0_03.
    (I do remember reading that 1.5x had issues too though). I also have the webserver (Windows 2003 Server OS)
    which has the Tomcat 5.5 running with jre 1.6.0_03. I basically ftp files up to the server after I test them locally on my box.

    I ran the code you gave on my local workstation in Eclipse. I was a bit confused on the code because I didn't
    know how to run it on my local workstation and point it to my java.security file without "modifying it".
    I kinda took your code "as is" and just changed it to run under the main method.
    So I guess I need to know how to modify it to make it look at my java.security file and / or configuration file
    in the code sample you gave me.

    Here is the part I THINK I would change, and how I would change it:
    From:
    String alias = null;
                  KeyStore lks = KeyStore.getInstance("PKCS11");
                  lks.load(null,null);
                  Provider p = lks.getProvider();
    To maybe something like:
    String alias = null;
                  KeyStore lks = KeyStore.getInstance("PKCS11");
                  lks.load(null,null);
    
    String configName = "C:/Program Files/Java/jre1.6.0_03/lib/security/pkcs11.cfg";
    Provider p = new sun.security.pkcs11.SunPKCS11(configName);
                   Security.addProvider(p);
              But I know from looking at it, that I'm not using the KeyStore object, so thats where I was a bit confused,
    so I just ran it "as is".



    Other topic, yes, card is inserted correctly =) Our setup is designed that we are FORCED to log into our
    Windows domain via smartcard. We do not have username / passwords anymore. So just by logging into
    the system / domain, I would say that my SCR and smartcard are functioning fine.

    I would like to test this on the webserver or locally, but either way, not sure how to implement the provider
    configuration into the code you gave me, sorry =(

    Thanks again for the help,

    SK

    Edited by: scryptkiddy on Apr 11, 2008 11:36 AM
  • 14. Re: PKCS11 & javax.net.ssl.keyStoreAlias
    843811 Newbie
    Currently Being Moderated
    Hi Sk,

    basically you can configure the provider stuff statically, as I did, or dynamically what you're trying to do.
    If you use your 'readKeyStoreFromSmartCard' class as it is, I would say try it first only statically.
    Therefore you have to add the provider line to your local windows jdk 1.6.0_03,
    not such a code like in your recent posting (...I THINK I would change, and how I would change it ...).

    Do you let your code run with THIS jdk and not with a maybe also existing separately installed JRE?
    Does your Eclipse really use THIS jdk, or uses it a maybe somehow bundled jdk installation in a different path?

    If you still have this line in your used JDK java.security file
    security.provider.10=sun.security.pkcs11.SunPKCS11 C:/Program Files/Java/jre1.6.0_03/lib/security/pkcs11.cfg
    and the card ist not flipped ;-) , IMHO, it can't say anymore 'PKCS11 not found'.

    Maybe all this is unnecessary, but I've right now not a better idea.
    Just to get sure display the system properties at the beginning of your code and check the java.home props and friends.
            
    Properties  props  = null;
    String      key    = null;
    
    props = System.getProperties();
    for (Enumeration en = props.propertyNames(); en.hasMoreElements(); ) {
    key = (String) en.nextElement();
    log.info("'" + key + "' = '" + (String) (props.get(key))+ "'");
    }
    One last thing, in the appended path of your provider line is a space between Program and Files.

    Maybe this is a problem.
    Try 2 things
    1. Use a path without spaces like I do with E:/pkcs11.cfg
    or
    2. Put the path in (double) quotes

    NX-01
1 2 Previous Next