KeyStore loading all certificates

0

I'm creating a webService that connects to the eSocial system, which requires authentication Mutual.

When I have only one certificate on the machine, there is no problem, but when it has 2+ certificates, I can not get the user to choose the certificate that made the connection, it simply creates the connection with the first one list certificate.

I would like the user to choose the certificate that he made the connection to.

When I give a simple in the KeyStore , it loads with all the certificates

KeyStore ks = KeyStore.getInstance("Windows-MY");
        InputStream io = tokenAladdin();
        try {
            ks.load(null, "@Techne".toCharArray());
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (CertificateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

I would like to know why the certificate choice window does not open.

Can anyone help me?

    
asked by anonymous 08.01.2018 / 20:35

2 answers

0

user101666, I'm also working with eSocial, but I'm developing in C # / VB.NET. In .NET there is a ready method that displays the dialog for the user to choose the desired certificate:

  

X509Certificate2UI.SelectFromCollection

Your code does not open a certificate choice window because you did not write anything to make it happen. Your code:

KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, "@Techne".toCharArray());

Only loads all the certificates stored in this Windows repository.

I did a quick search on this functionality in Java and found this post in the global StackOverflow:

  

link

There Florian user says that this functionality does not exist ready in Java, but that he wrote a solution in Java to display the Windows dialog for choice of certificate. He put the project in GitHub:

  

link

And to get that solution, he relied on that other Tech Junkie post:

  

link

But basically what they did was to directly access the CryptUIDlgSelectCertificateFromStore function of the Cryptui.dll library, native to Windows:

  

link

I will replicate here the code posted by the user Tech Junkie , which is easier to post if the links stop working:

NativeLibrary cryptUI = NativeLibrary.getInstance("Cryptui");
NativeLibrary crypt32 = NativeLibrary.getInstance("Crypt32");

Function functionCertOpenSystemStore = crypt32.getFunction("CertOpenSystemStoreA");
Object[] argsCertOpenSystemStore = new Object[] { 0, "CA"};
HANDLE h = (HANDLE) functionCertOpenSystemStore.invoke(HANDLE.class, argsCertOpenSystemStore);

Function functionCryptUIDlgSelectCertificateFromStore = cryptUI.getFunction("CryptUIDlgSelectCertificateFromStore");
System.out.println(functionCryptUIDlgSelectCertificateFromStore.getName());
Object[] argsCryptUIDlgSelectCertificateFromStore = new Object[] { h, 0, 0, 0, 16, 0, 0};
Pointer ptrCertContext = (Pointer) functionCryptUIDlgSelectCertificateFromStore.invoke(Pointer.class, argsCryptUIDlgSelectCertificateFromStore);

Function functionCertGetNameString = crypt32.getFunction("CertGetNameStringW");
char[] ptrName = new char[128];
Object[] argsCertGetNameString = new Object[] { ptrCertContext, 5, 0, 0, ptrName, 128};
functionCertGetNameString.invoke(argsCertGetNameString);
System.out.println("Selected certificate is " + new String(ptrName));

Function functionCertFreeCertificateContext = crypt32.getFunction("CertFreeCertificateContext");
Object[] argsCertFreeCertificateContext = new Object[] { ptrCertContext};
functionCertFreeCertificateContext.invoke(argsCertFreeCertificateContext);

Function functionCertCloseStore = crypt32.getFunction("CertCloseStore");
Object[] argsCertCloseStore = new Object[] { h, 0};
functionCertCloseStore.invoke(argsCertCloseStore);

I hope it helps.

    
20.02.2018 / 05:15
0

I just solved it via msm code, however I present a simple combo box, and I get the alias of the certificate, then implement it only in a "KeyManager Array";

 KeyStore ksPrivate = KeyStore.getInstance("JKS");
 KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection("tEHCNE@".toCharArray()));

 ksPrivate.load(null, null);
 X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
 //keySotre2.setKeyEntry("key1", (Key)keyEntry.getPrivateKey(), "tECHNE@".toCharArray(), certChain);  
 //keySotre2.setEntry(alias, keyEntry, protParam);

 HSKeyManager hsKey = new HSKeyManager(cert, keyEntry.getPrivateKey());  

 KeyManager[] keysManager = new KeyManager[]{hsKey};

Then I just need to set this key store on the connection

sslContext.init(keysManager, tmf.getTrustManagers(), new SecureRandom());

HSKeyManager object.

import java.net.Socket;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509KeyManager;

public class HSKeyManager implements X509KeyManager {

    private X509Certificate certificate;  
        private PrivateKey privateKey;  

        public HSKeyManager(X509Certificate certificate, PrivateKey privateKey) {  
            this.certificate = certificate;  
            this.privateKey = privateKey;  
        }  

        public String chooseClientAlias(String[] arg0, Principal[] arg1,  
                Socket arg2) {  
            return certificate.getIssuerDN().getName();  
        }  

        public String chooseServerAlias(String arg0, Principal[] arg1,  
                Socket arg2) {  
            return null;  
        }  

        public X509Certificate[] getCertificateChain(String arg0) {  
            return new X509Certificate[]{certificate};  
        }  

        public String[] getClientAliases(String arg0, Principal[] arg1) {  
            return new String[]{certificate.getIssuerDN().getName()};  
        }  

        public PrivateKey getPrivateKey(String arg0) {  
            return privateKey;  
        }  

        public String[] getServerAliases(String arg0, Principal[] arg1) {  
            return null;  
        } 
}

Then I'll try your solution

    
23.02.2018 / 14:02