makdimka077 / xades4j

Automatically exported from code.google.com/p/xades4j
GNU Lesser General Public License v3.0
0 stars 0 forks source link

Please help passing PIN to smartcard used with PKCS11KeyStoreKeyingDataProvider #33

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hi,
I am trying to use XadES with my smartcard to sign documents.

I faced the following problem. In "native" sunPKCS11 implementation you can do 
the following:

    public static void main(String args[]) {

    if (args.length != 2) {
        usage();
        System.exit(1);
    }
    String configName = args[0];

    Provider p = new sun.security.pkcs11.SunPKCS11(configName);
    Security.addProvider(p);
    Provider[] providers = Security.getProviders();
    for (int i = 0; i < providers.length; i++) {
        System.out.println("Provider " + i + ": "
            + providers[i].getName());
    }
    try {
        KeyStore.PasswordProtection pwd = new KeyStore.PasswordProtection(args[1].toCharArray());
        KeyStore ks = KeyStore.getInstance("PKCS11", p);
        ks.load(null, pwd.getPassword());
....   

    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Wrong password");
    }
    }

I am interested in ks.load(null, pwd.getPassword());
I have no clue how to pass card password to XadES, which is done by ks.load 
from the script above.

I started from 
        keyingDataProvider = new PKCS11KeyStoreKeyingDataProvider(
            nativeLibrary,
            providerName,
            new FirstCertificateSelector(),
            null,
            null,
            true);

and wanted to use that object, but it seems that keystore object held by that 
object is private. I can't access it and can't pass pin for the smartcard.

Could you point me to right direction please?

Thank you in advance

Best regards
Norbert

Original issue reported on code.google.com by n...@tronix.pl on 26 Feb 2012 at 6:20

GoogleCodeExporter commented 9 years ago
Hi. You're going in the right direction by using that constructor of 
PKCS11KeyStoreKeyingDataProvider. The class has different constructors for 
different scenarios. If you check the java docs, the parameters that are being 
passed null are key store and entry password providers, respectively. Some 
smart card native libraries handle PIN requests on their own; that's why the 
parameters can be null.

On your scenario you need to specify a KeyStorePasswordProvider. An interface 
is used instead of directly supplying the password to allow scenarios where the 
password is obtained on demand (from user input, for instance).

Hope this helps. I'm leaving this issue open until you come back with some 
feedback. In the future please use the Q&A wiki section since this isn't really 
an issue.

Original comment by luis.fgoncalv on 26 Feb 2012 at 9:48

GoogleCodeExporter commented 9 years ago
Hi,
Thank you very much for prompt answer and sorry for publishing to issues.

Unfortunately I am just starting work with java, and although read some books, 
have almost no practical knowledge, that's way shame on me, but probably I am 
asking for trivial thing.

Before and after posting the first post I was experimenting with passing 
arguments, but I was unable to initiate (or pass) the 
KeyStoreKeyingDataProvider.KeyStorePasswordProvider properly.

Finally I understood, and it is the first time I managed to run the code ... 
simple I just needed to implement the KeyStorePasswordProvider, just according 
to your advice, so I put into my code:

public class KeyStorePasswordProvider implements 
KeyStoreKeyingDataProvider.KeyStorePasswordProvider{
    @Override
    public char[] getPassword() {
    String password="mypassword";
    return password.toCharArray();
    }
}

and

keyingDataProvider = new PKCS11KeyStoreKeyingDataProvider(
    nativeLibrary,
    providerName,
    new FirstCertificateSelector(),
    new KeyStorePasswordProvider(),
    null,
    true);

System.out.println(keyingDataProvider.getSigningCertificateChain().toString());

however

1. get the exception:

2012-02-27 01:16:13 main main
SEVERE: null
java.security.KeyStoreException: Can't initialize Sun PKCS#11 security provider.
Reason: xades4j.verification.UnexpectedJCAException: The keystore couldn't be 
initialized
        at XadES.XADES.getSigningCertificateChain(XADES.java:45)
        at main.main(main.java:13)

2. Although I implemented the interface, I don't understand how can I pass card 
password (now it is just written in the code).

Could you help me further please.

Thanks in advance

Brgs
Norbert

Original comment by n...@tronix.pl on 27 Feb 2012 at 12:18

GoogleCodeExporter commented 9 years ago
When you get some sleep, you think better :-)
Just realized that I can add a constructor and pass the password via the 
constructor. 

public class KeyStorePasswordProvider implements 
KeyStoreKeyingDataProvider.KeyStorePasswordProvider{
    private String password;

    @Override
    public char[] getPassword() {
    return password.toCharArray();
    }

    public KeyStorePasswordProvider(String password) {
    this.password=password;
    }

}

Now, I successfully accessed my smartcard.
More questions will send through Q&A.

Thank you very much for your help.

Brgs
Norbert

Original comment by n...@tronix.pl on 27 Feb 2012 at 8:55

GoogleCodeExporter commented 9 years ago
Yes, that would be it. You're welcome!

Original comment by luis.fgoncalv on 27 Feb 2012 at 9:30

GoogleCodeExporter commented 9 years ago
hi
you can to share for me this source code? thanks alot

Original comment by minh...@gmail.com on 30 Jul 2012 at 3:33