/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package sample.applet;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import java.util.Enumeration;
import java.util.Properties;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

/**
 *
 * @author ricky
 */
public class PKCS11Signer extends JCESigner {

    final static public String PKCS11_NAME = "sample.applet.pkcs11Name";

    private String name = null;

    static public class PKCS11Callback implements CallbackHandler {

        private String password = null;

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

        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            for (int i = 0; i < callbacks.length; i++) {
                if (callbacks[i] instanceof PasswordCallback) {
                    PasswordCallback pc = (PasswordCallback) callbacks[i];
                    System.err.print(pc.getPrompt());
                    System.err.flush();
                    pc.setPassword(password.toCharArray());
                } else {
                    throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
                }
            }
        }
    }

    @Override
    public void setProperties(Properties props) throws Exception {
        name = props.getProperty(PKCS11_NAME);
        if (name == null) {
            throw new Exception(new StringBuffer(PKCS11_NAME).append(
                    " have to be provided.").toString());
        }
        // common properties
        parseCommomprops(props);
        // create the names
        this.keyStoreType = "PKCS11";
        this.providerType = "SunPKCS11-" + name;
        // check if the provider is already registered
        if (Security.getProvider(this.providerType) == null) {
            // register the provider adding all the rest of properties as lines
            StringBuffer sb = new StringBuffer();
            sb.append("name = ");
            sb.append(name);
            sb.append(System.getProperty("line.separator"));
            Enumeration keys = props.keys();
            while (keys.hasMoreElements()) {
                String key = (String) keys.nextElement();
                if (!key.startsWith("sample.applet.")) {
                    sb.append(key);
                    sb.append(" = ");
                    sb.append(props.getProperty(key));
                    sb.append(System.getProperty("line.separator"));
                }
            }
//          sb.append("nssLibraryDirectory = /usr/lib/");
//          sb.append(System.getProperty("line.separator"));
//          sb.append("nssSecmodDirectory = /home/ricky/.mozilla/firefox/lqzn9ms9.default");
//          sb.append(System.getProperty("line.separator"));
//          sb.append("nssModule = keystore");
//          sb.append(System.getProperty("line.separator"));
//          sb.append("nssDbMode = readOnly");
//          sb.append(System.getProperty("line.separator"));
            byte[] byteArray = sb.toString().getBytes(System.getProperty("file.encoding"));
            ByteArrayInputStream baos = new ByteArrayInputStream(byteArray);
            Provider p = new sun.security.pkcs11.SunPKCS11(baos);
            Security.addProvider(p);
        }
    }

    @Override
    public void initialize(String password) throws Exception {
        this.keyStorePassword = password;
        keyStore = KeyStore.getInstance(keyStoreType);
        if (password != null) {
            keyStore.load(null, password.toCharArray());
        } else {
            keyStore.load(null, null);
        }
//        KeyStore.CallbackHandlerProtection callback = new KeyStore.CallbackHandlerProtection(
//                new PKCS11Callback(password)) ;
//        KeyStore.Builder builder = KeyStore.Builder.newInstance(keyStore, callback);
//        keyStore = builder.getKeyStore();
//        keyStore.getCertificate("CIFRADO");
    }
}

