Could not create RSA Public key (PKCS11)

Hi,

I implemented a method for verify a digital signature by public key contains in SmartCard. I want this process will be sucessfully in a SmartCard.

This code, provoke an exception :

<InvalidKeyException Could not create RSA Public key>

I think that the problem is in the driver pkcs11 for the smartcard. The provider is SunPKCS11-ceres and the sign and decrypt running very well.

Thanks and best regards

public class VerSig {

public static void main(String[] args) {

/* Verify a DSA signature */

if (args.length != 1) {

System.out.println("Usage: VerSig signaturefile");

} else

try {

String configName = "ceres_linux.cfg"; // ceres_windows.cfg for windows

Provider p = new sun.security.pkcs11.SunPKCS11(configName);

System.out.println(p);

Security.addProvider(p);

//Obtenemos el fichero a firmar

//Iniciamos el acceso a los certificados almacenados en la tarjeta.eres

KeyStore keyStore = KeyStore.getInstance("PKCS11","SunPKCS11-ceres");

char[] pin = "changeit".toCharArray();

keyStore.load(null, pin);

//Obtenemos la clave privada para realizar la firma del documento.

Enumeration enumeration = keyStore.aliases();

String stringCertificado = enumeration.nextElement().toString();

// Printing alias

System.out.println("Alias="+stringCertificado);

Certificate certificado = keyStore.getCertificate(stringCertificado);

Key key = keyStore.getKey(stringCertificado, pin);

PublicKey pub = keyStore.getCertificate(stringCertificado).getPublicKey();

/* input the signature bytes */

FileInputStream sigfis = new FileInputStream(args[0]);

byte[] sigToVerify = new byte[sigfis.available()];

sigfis.read(sigToVerify);

sigfis.close();

/*

* create a Signature object and initialize it with the public

* key

*/

Signature sig = Signature.getInstance("SHA1withRSA","SunPKCS11-ceres");

sig.initVerify(pub); ///// The problem is here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1

/* Data to sign */

byte[] data = new String("This data is to test a signature").getBytes();

/* Update and verify the data */

sig.update(data);

boolean verifies = sig.verify(sigToVerify);

System.out.println("signature verifies: " + verifies);

} catch (Exception e) {

e.printStackTrace(System.err);

System.err.println("Caught exception " + e.toString());

}

}

}

[2591 byte] By [PKCS11a] at [2007-10-3 4:19:07]
# 1
Can you paste the PEM-encoded certificate that is on your smartcard on the forum?
arshad.noora at 2007-7-14 22:20:53 > top of Java-index,Security,Cryptography...
# 2

Hi,

I'm alexei, and this is my certificate. I login with other user why, I forgot the password of PKCS11 user.

--BEGIN CERTIFICATE--

MIIFPDCCBKWgAwIBAgIEPIlKfzANBgkqhkiG9w0BAQUFADA2MQswCQYDVQQGEwJFUzENMAsGA1UEChMERk5NVDEYMBYGA1UECxMPRk5NVCBDbGFzZSAyIENBMB4XDTA2MDUy

NDE5MzgxM1oXDTA5MDUyNDE5MzgxM1owgYExCzAJBgNVBAYTAmVzMQ0wCwYDVQQKEwRGTk1UMRgwFgYDVQQLEw9mbm10IGNsYXNlIDIgY2ExEjAQBgNVBAsTCTcwMzAxMzA1

MzE1MDMGA1UEAxMsTk9NQlJFIEhPUk5***8gSU5DRVJBIEFMRVhFSSAtIE5JRiAyODk2OTU5NEowgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOYTpQtfO+3MndG0FtNd

SqrCrYmGLjeUcHiqoDywsbYpF34IzSK1weC7RaXXwMDZ37MSCLy5RmG/Cyc2OuNmRaMGRFnae30BtOIvhNA90kVqPfdbehxANNvgmQZgNnYf2h3QUOUJBH9/cd3jhEj32PBQ

LIov3nC37THXT9AKzSRdAgMBAAGjggMJMIIDBTCBiAYDVR0RBIGAMH6BGEFMRVhFSS5IT1JORVJPQEdNQUlMLkNPTaRiMGAxGDAWBgkrBgEEAaxmAQQTCTI4OTY5NTk0SjEV

MBMGCSsGAQQBrGYBAxMGSU5DRVJBMRYwFAYJKwYBBAGsZgECEwdIT1JORVJPMRUwEwYJKwYBBAGsZgEBEwZBTEVYRUkwCQYDVR0TBAIwADArBgNVHRAEJDAigA8yMDA2MDUy

NDE5MzgxM1qBDzIwMDkwNTI0MTkzODEzWjALBgNVHQ8EBAMCBaAwEQYJYIZIAYb4QgEBBAQDAgWgMB0GA1UdDgQWBBRGMjp+FqJHgyzcHNq1dVNlJkGpsDAfBgNVHSMEGDAW

gBRAmnZEl3QHxKwUyx6NTzpFfDDXYTCCATEGA1UdIASCASgwggEkMIIBIAYJKwYBBAGsZgMFMIIBETA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5jZXJ0LmZubXQuZXMvY29u

dmVuaW8vZHBjLnBkZjCB2AYIKwYBBQUHAgIwgcsagchDZXJ0aWZpY2FkbyBSZWNvbm9jaWRvIGV4cGVkaWRvIHNlZ/puIGxlZ2lzbGFjafNuIHZpZ2VudGUuVXNvIGxpbWl0

YWRvIGEgbGEgQ29tdW5pZGFkIEVsZWN0cvNuaWNhIHBvciB2YWxvciBt4XhpbW8gZGUgMTAwIGUgc2Fsdm8gZXhjZXBjaW9uZXMgZW4gRFBDLkNvbnRhY3RvIEZOTVQ6Qy9K

b3JnZSBKdWFuIDEwNi0yODAwOS1NYWRyaWQtRXNwYfFhLjAdBgkrBgEEAaxmASEEEBYOUEVSU09OQSBGSVNJQ0EwLwYIKwYBBQUHAQMEIzAhMAgGBgQAjkYBATAVBgYEAI5G

AQIwCxMDRVVSAgFkAgEAMFsGA1UdHwRUMFIwUKBOoEykSjBIMQswCQYDVQQGEwJFUzENMAsGA1UEChMERk5NVDEYMBYGA1UECxMPRk5NVCBDbGFzZSAyIENBMRAwDgYDVQQD

EwdDUkwyNjE2MA0GCSqGSIb3DQEBBQUAA4GBACLTl4RDIogMYEEJrIm2c9BQDYNyGOF4jv0YHkdo5odnWtMpQTisjYqY4QMGn1k754pIbXtA8EAihJbP9dOqUV9qatQhIwS6

XI6Du/1TpJedYA898AsCF2JXcIg0DZ+NDAngfb4ZsCUjKtA3suRgHE1mJE4d7R+yeh8izdzUcPu9

--END CERTIFICATE--

Thanks, best regards

alexhora at 2007-7-14 22:20:53 > top of Java-index,Security,Cryptography...
# 3

The problem could be that you're working with interfaces (Certificate and Key) rather than the actual implementations (X509Certificate and PublicKey). The method Certificate.getPublicKey() is abstract - http://java.sun.com/j2se/1.5.0/docs/api/java/security/cert/Certificate.html#getPublicKey() - and while it will successfully compile, there will be no real method to call at run-time.

Try using the real classes with implemented methods (X509Certificate, PublicKey, PrivateKey) and see if it makes a difference in your environment. Additionally, you can review the source code of the keyStoreLoaderHelper.java source code in the StrongKey distribution at www.strongkey.org to see how this software product extracts the Public and Private keys from smartcards.

arshad.noora at 2007-7-14 22:20:53 > top of Java-index,Security,Cryptography...
# 4

Hi,

I am also signing with a key on a smartcard.

I have fixed you code :)

Try changing the following

KeyStore keyStore = KeyStore.getInstance("PKCS11");

...

Signature sig = Signature.getInstance("SHA1withRSA", p);

...

/* input the signature bytes */

/*

This is not needed ?

FileInputStream sigfis = new FileInputStream(args[0]);

byte[] sigToVerify = new byte[sigfis.available()];

sigfis.read(sigToVerify);

sigfis.close();

*/

/* Sign Data */

byte[] data = new String("This data is to test a signature").getBytes();

sig.initSign((PrivateKey)key);

sig.update(data);

byte[] sigBytes = sig.sign();

System.out.println("Signature: >" + new String(sigBytes) + "<");

/* Check Signature */

Signature signer = Signature.getInstance("SHA1withRSA");

signer.initVerify(pub);

signer.update(data);

boolean verifies = signer.verify(sigBytes);

System.out.println("signature verifies: " + verifies);

The signature now verifies true.

If you would like to ensure you always have the signing certificate check this thread out:

It has an example I gave of check using the getKeyUsage() method.

If you need any more help just post back (with code !)

** Phill **

pcama at 2007-7-14 22:20:53 > top of Java-index,Security,Cryptography...