It does not represent the only one way how to achieve the desired result, especially when it comes to manipulation with certificates and keys certificate management.
Loading Certificate into the Card
It seems that the easiest approach is to prepare the key store on disk and load it into the card when ready. For that we use mostly two tools - openssl to transform keys and certificates and keytool to manage the key store.
Create the key store on disk and fill with certificates
Create a private key entry, i.e. a certificate containing a private key, by converting our certificate and private key to PKCS12 format: openssl pkcs12 -export -out cert.p12 -in cert.pem -inkey key.pem
I used org.apache.commons.ssl.KeyStoreBuilder to build a keystore from the p12 file. The password is used both for decryption of private key and encryption of the newly created Java key store.
java -cp commons-ssl.jar org.apache.commons.ssl.KeyStoreBuilder password cert.p12
Now you can check the content of the file-based key store: keytool -keystore newkeystore.jks -listjava -cp commons-ssl.jar org.apache.commons.ssl.KeyStoreBuilder password cert.p12
Load the file-base key store into the card
keytool -keystore NONE -storetype PKCS11 -providerName SunPKCS11-OpenSC-PKCS11 -importkeystore -srckeystore newkeystore.jks
Check the content of the on-card key store.
keytool -keystore NONE -storetype PKCS11 -providerName SunPKCS11-OpenSC-PKCS11 -list
Signing and Verification with the On-Card Certificate
All the error handling was intentionally removed to make following example shorter. I also skipped creation of PKCS7 signed messages - you can you Bouncy Castle CMSSignedDataGenerator for that easily.
import java.security.*; import java.security.cert.*; import java.security.cert.Certificate; import java.io.*; ... // loading the key from file: KeyStore keyStore = KeyStore.getInstance("JCEKS"); FileInputStream inputStream = new FileInputStream(storeFileName); keyStore.load(inputStream, storePassword.toCharArray()); KeyStore.ProtectionParameter protectParameter = new KeyStore.PasswordProtection(certPass.toCharArray()); } // loading the key from token: KeyStore keyStore = KeyStore.getInstance("PKCS11"); KeyStore.ProtectionParameter protectParameter = null; keyStore.load(null, storePassword.toCharArray()); // the rest does not depend on the type of the store: String signatureAlgorithmName = "SHA1withRSA"; KeyStore.Entry entry = keyStore.getEntry(alias, protectParam); boolean isPrivateKeyEntry = keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class); if (isPrivateKeyEntry) { Signature signatureAlgorithm = Signature.getInstance(signatureAlgorithmName); // signing KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)entry; PrivateKey privateKey = privateKeyEntry.getPrivateKey(); signatureAlgorithm.initSign (privateKey); signatureAlgorithm.update (message); byte[] signature = signatureAlgorithm.sign(); // verification Certificate[] chain = privateKeyEntry.getCertificateChain(); X509Certificate certificate = (X509Certificate) chain[chain.length-1]; PublicKey publicKey = certificate.getPublicKey(); signatureAlgorithm.initVerify(publicKey); signatureAlgorithm.update (data); boolean verified = signatureAlgorithm.verify(signature); }
No comments:
Post a Comment