Please find the Java version and the .net version i used.
Java
import java.applet.Applet;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.security.*;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.lang.reflect.Constructor;
//import netscape.javascript.JSException;
//import netscape.javascript.JSObject;
//import javax.mail.internet.MimeUtility;
/**
* Applet for digital signing documents with a smart card. The applet is intended to
* be placed in a HTML document containing a single HTML form that is used for applet
* input/output. The applet accepts several parameters - the name of the field in the
* HTML form that contains the file name to be signed and the names of the fields in
* the HTML form, where the certification chain and signature should be stored.
*
* If the signing process is sucecssfull, the signature and certification chain fields
* in the HTML form are filled. Otherwise an error message explaining the failure
* reason is shown.
*
* The applet asks the user to locate in his local file system the PKCS#11
* implementation library that is part of software that come with the smart card
* and the smart card reader. Usually this is a Windows .DLL file located in Windows
* system32 directory or .so library (e.g. C:\windows\system32\pkcs201n.dll).
*
* The applet also asks the user to enter his PIN code for accessing the smart card.
* If the smart card contains a certificate and a corresponding private key, the
* signature of the file is calculated and is placed in the HTML form. In addition
* to the calculated signature the certificate with its full certification chain is
* extracted from the smart card and is placed in the HTML form too. The digital
* signature is placed as Base64-encoded sequence of bytes. The certification chain
* is placed as ASN.1 DER-encoded sequence of bytes, additionally encoded in Base64.
* In case the smart card contains only one certificate without its full certification
* chain, a chain consisting of this single certificate is extracted and stored in the
* HTML form instead of a full certification chain.
*
* Digital singature algorithm used is SHA1withRSA. The length of the calculated
* singature depends on the length of the private key on the smart card.
*
* The applet should be able to access the local machine's file system for reading and
* writing. Reading the local file system is required for the applet to access the file
* that should be signed. Writing the local file system is required for the applet to
* save its settings in the user's home directory. Accessing the local file system is
* not possible by default, but if the applet is digitally signed (with jarsigner), it
* runs with no security restrictions and can do anything. This applet should be signed
* in order to run.
*
* Java Plug-In version 1.5 or hihger is required for accessing the PKCS#11 smart card
* functionality, so the applet will not run in any other Java runtime environment.
*
* This file is part of NakovDocumentSigner digital document
* signing framework for Java-based Web applications:
* http://www.nakov.com/documents-signing/
*
* Copyright (c) 2005 by Svetlin Nakov - http://www.nakov.com
* All rights reserved. This code is freeware. It can be used
* for any purpose as long as this copyright statement is not
* removed or modified.
*/
public class SmartCardSignerApplet extends Applet {
private static final String FILE_NAME_FIELD_PARAM = "fileNameField";
private static final String CERT_CHAIN_FIELD_PARAM = "certificationChainField";
private static final String SIGNATURE_FIELD_PARAM = "signatureField";
private static final String SIGN_BUTTON_CAPTION_PARAM = "signButtonCaption";
private static final String VERIFY_BUTTON_CAPTION_PARAM = "verifyButtonCaption";
private static final String PKCS11_KEYSTORE_TYPE = "PKCS11";
private static final String X509_CERTIFICATE_TYPE = "X.509";
private static final String CERTIFICATION_CHAIN_ENCODING = "PkiPath";
private static final String DIGITAL_SIGNATURE_ALGORITHM_NAME = "SHA1withRSA";
private static final String SUN_PKCS11_PROVIDER_CLASS = "sun.security.pkcs11.SunPKCS11";
private Button mSignButton;
private Button mVerifyButton;
/**
* Initializes the applet - creates and initializes its graphical user interface.
* Actually the applet consists of a single button, that fills its all surface. The
* button's caption is taken from the applet parameter SIGN_BUTTON_CAPTION_PARAM.
*/
public void init() {
String signButtonCaption = this.getParameter(SIGN_BUTTON_CAPTION_PARAM);
mSignButton = new Button("Sign");
mSignButton.setLocation(0, 0);
Dimension appletSize = this.getSize();
mSignButton.setSize(appletSize.width/2, appletSize.height);
//mSignButton.setSize(appletSize);
mSignButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
signSelectedFile();
}});
this.setLayout(null);
this.add(mSignButton);
// verify button
String verifyButtonCaption = this.getParameter(VERIFY_BUTTON_CAPTION_PARAM);
mVerifyButton = new Button("Verify");
// Dimension appletSize = this.getSize();
mVerifyButton.setLocation(appletSize.width/2+1, 0);
mVerifyButton.setSize(appletSize.width/2, appletSize.height);
mVerifyButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
verifySignature();
}});
this.setLayout(null);
this.add(mVerifyButton);
}
/**
* Signs the selected file. The file name comes from a field in the HTML document.
* The result consists of the calculated digital signature and certification chain,
* both placed in fields in the HTML document, encoded in Base64 format. The HTML
* document should contain only one HTML form. The name of the field, that contains
* the name of the file to be signed is obtained from FILE_NAME_FIELD_PARAM applet
* parameter. The names of the output fields for the signature and the
* certification chain are obtained from the parameters CERT_CHAIN_FIELD_PARAM
* and SIGNATURE_FIELD_PARAM. The user is asket to choose a PKCS#11 implementation
* library and a PIN code for accessing the smart card.
*/
private void signSelectedFile() {
try {
// Get the file name to be signed from the form in the HTML document
// JSObject browserWindow = JSObject.getWindow(this);
// JSObject mainForm = (JSObject) browserWindow.eval("document.forms[0]");
// String fileNameFieldName = this.getParameter(FILE_NAME_FIELD_PARAM);
// JSObject fileNameField = (JSObject) mainForm.getMember(fileNameFieldName);
// String fileName = (String) fileNameField.getMember("value");
// Perform the actual file signing
String texttosign = "test";
CertificationChainAndSignatureBase64 signingResult = signFile(texttosign);
if (signingResult != null) {
System.out.println(signingResult.mCertificationChain);
System.out.println(signingResult.mSignature);
// Document signed. Fill the certificate and signature fields
// String certChainFieldName = this.getParameter(CERT_CHAIN_FIELD_PARAM);
// JSObject certChainField = (JSObject) mainForm.getMember(certChainFieldName);
// certChainField.setMember("value", signingResult.mCertificationChain);
// String signatureFieldName = this.getParameter(SIGNATURE_FIELD_PARAM);
// JSObject signatureField = (JSObject) mainForm.getMember(signatureFieldName);
// signatureField.setMember("value", signingResult.mSignature);
} else {
// User canceled signing
}
}
catch (DocumentSignException dse) {
// Document signing failed. Display error message
String errorMessage = dse.getMessage();
JOptionPane.showMessageDialog(this, errorMessage);
}
catch (SecurityException se) {
se.printStackTrace();
JOptionPane.showMessageDialog(this,
"Unable to access the local file system.\n" +
"This applet should be started with full security permissions.\n" +
"Please accept to trust this applet when the Java Plug-In ask you.");
}
/*catch (JSException jse) {
jse.printStackTrace();
JOptionPane.showMessageDialog(this,
"Unable to access some of the fields of the\n" +
"HTML form. Please check the applet parameters.");
}*/
catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this, "Unexpected error: " + e.getMessage());
}
}
public static boolean verifySig(byte[] data, PublicKey key, byte[] sig) throws Exception {
Signature signer = Signature.getInstance("SHA1withRSA");
signer.initVerify(key);
signer.update(data);
return (signer.verify(sig));
}
private void verifySignature(){
try {
// Get the file name to be signed from the form in the HTML document
// JSObject browserWindow = JSObject.getWindow(this);
// JSObject mainForm = (JSObject) browserWindow.eval("document.forms[0]");
// String fileNameFieldName = this.getParameter(FILE_NAME_FIELD_PARAM);
// JSObject fileNameField = (JSObject) mainForm.getMember(fileNameFieldName);
// String fileName = (String) fileNameField.getMember("value");
// Document signed. Fill the certificate and signature fields
// String certChainFieldName = this.getParameter(CERT_CHAIN_FIELD_PARAM);
// JSObject certChainField = (JSObject) mainForm.getMember(certChainFieldName);
// String certText = (String) certChainField.getMember("value");
//certChainField.setMember("value", signingResult.mCertificationChain);
// String signatureFieldName = this.getParameter(SIGNATURE_FIELD_PARAM);
// JSObject signatureField = (JSObject) mainForm.getMember(signatureFieldName);
// String signatureText = (String) signatureField.getMember("value");
//signatureField.setMember("value", signingResult.mSignature);
//PKCS11LibraryFileAndPINCodeDialog pkcs11Dialog =
// new PKCS11LibraryFileAndPINCodeDialog();
//boolean dialogConfirmed;
//try {
// dialogConfirmed = pkcs11Dialog.run();
//} finally {
// pkcs11Dialog.dispose();
//}
//if (dialogConfirmed) {
String oldButtonLabel = mVerifyButton.getLabel();
mVerifyButton.setLabel("Working...");
mVerifyButton.setEnabled(false);
try {
//String pkcs11LibraryFileName = pkcs11Dialog.getLibraryFileName();
//String pkcs11LibraryFileName = "C:\\WINDOWS\\system32\\WatchData\\Egypt Trust CSP V1.0\\WDPKCS.dll";
//String winPath = System.getenv("windir");
//String pkcs11LibraryFileName = winPath + "\\system32\\EgyptTrust\\Egypt Trust CSP V1.0\\WDPKCS.dll";
//String pinCode = pkcs11Dialog.getSmartCardPINCode();
//KeyStore userKeyStore = loadKeyStoreFromSmartCard(pkcs11LibraryFileName, pinCode);
//Enumeration aliasesEnum = userKeyStore.aliases();
//String alias = (String)aliasesEnum.nextElement();
//PublicKey publicKey = (PublicKey) userKeyStore.getKey(alias, null);
//Certificate[] certificationChain = userKeyStore.getCertificateChain(alias);
//PublicKey publicKey = certificationChain[0].getPublicKey();
Certificate cert = null;
CertificateFactory cf = CertificateFactory.getInstance(X509_CERTIFICATE_TYPE);
cert = cf.generateCertificate(new ByteArrayInputStream(Base64Utils.base64Decode("MIIEhDCCA2ygAwIBAgIQX6SWkoV/Wo5jeyTwm5qxcDANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJFRzEUMBIGA1UEChMLRWd5cHQgVHJ1c3QxLDAqBgNVBAMTI0VneXB0IFRydXN0IE1TIERvbWFpbiBMb2dvbiBUZXN0IENBMB4XDTEwMDkwODAwMDAwMFoXDTExMDkwODIzNTk1OVowgeQxFDASBgNVBAoUC0VneXB0IFRydXN0MRAwDgYDVQQLFAdNU2xvZ29uMSUwIwYDVQQLFBxOYXRpb25hbCBJRCAtIDI2NjExMDUwMTAzOTMyMSAwHgYDVQQLFBdNdWJhc2hlciBOTyAtIDI3MjEwNTE0MDE0MDIGA1UECxQrUHVycG9zZSAtIERpcmVjdCBCcm9rZXIgZm9yIFNlY3VyaXRpZXMgdGVzdDEXMBUGA1UEAxMOQXNocmFmIFNvbGltYW4xIjAgBgkqhkiG9w0BCQEWE2FzaHJhZkBtdWJhc2hlci5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+Uoiy/L5E1hOeuQdzXLQVeEJbg4iuoPSmyy1HZJJI32AfFtZCdppU5LwreYJAtdUGxFXkwNyTmT+pBe9jjs0ClUdP4fZalH5a+J9u7MwdTgGWW0XXwkJRoy2qcoQE/BZfLxUUbbcueFt/l55YUj5hzBGq+K6SeFbY09a7wGRtHnYlUKZuaOhQzf+B3u3K2uknBDLdZpl+cQRkW7/thq6HGsow3zz4LOHP5SfYJlgpbQ9Fjgq98+NZqACEehQKJrNJ1c7LCNTr687Lyc4mTy4PR5yJ88Gzow6owpez80X49R0xBLzBpugzGq+yY+miloBNe2piSsTz4JkPGxl/hUhHAgMBAAGjgcMwgcAwCQYDVR0TBAIwADAeBgNVHREEFzAVgRNhc2hyYWZAbXViYXNoZXIubmV0MFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly9tcGtpY3JsLXBpbG90LmVneXB0dHJ1c3QuY29tL0VneXB0VHJ1c3RNU2xvZ29uL0xhdGVzdENSTC5jcmwwCwYDVR0PBAQDAgWgMB0GA1UdDgQWBBTdGtuvuhng5jB41dTLUgqNwLWXbjARBglghkgBhvhCAQEEBAMCB4AwDQYJKoZIhvcNAQEFBQADggEBAC7FtUWZRguM5eLN+snpN1QIS5eC9I40zTnaOaTt3Wuks+GuzoKpFLo0zDEMJMMDoHT4A25aCWi7CPxgiaDQR9nYEfcVW69m6ijD/wHgHHDZovKtzJxXk8WXfxnQU+lMl/NoDXqoBaJySrpYOG4HVs/FblmafdUO5AR6hCJx9nvToZ07RLw8vMRblthiyOOgAUdW270NFAlVDtC5F5j0mhaFp+/Q5hgEzOqj7o/YljpXTG4rFmB3Tx2EqE8lP9Y6ZVNVOXCCVOWxFTrnVRNVx2+1s7HzoX8GV0E+AINItnW4I2EuJBCom5bz0s1+rXZwLepnfv0vudRGl052waJSP1s=")));//certification text
PublicKey publicKey = cert.getPublicKey();
//JOptionPane.showMessageDialog(this,certText);
//Collection c = CertificateFactory
// .getInstance(X509_CERTIFICATE_TYPE)
// .generateCertificate(new ByteArrayInputStream(Base64Utils.base64Decode(certText)));
//Iterator i = c.iterator();
//while (i.hasNext()) {
// cert = (Certificate)i.next();
//}
//if(cert== null)
//{
// JOptionPane.showMessageDialog(this,certText);
//}
//PublicKey publicKey = cert.getPublicKey();
//PublicKey publicKey = certs.getPublicKey();//myCert.getPublicKey();
boolean IsValid = verifySig("test".getBytes(), publicKey, Base64Utils.base64Decode(
"kx02v6soJ2tZQR3+OwSchB/5iL3Q6ziOVlw/k2+NlHpEutNuwzJUpaXCGrhwqMcS3JzVnzG7ELx9eIgsIWxqAats+bqjrWtv0MpY3GgrxbaB6REwmshi4z9MRJG5lIADGZCJSpPqTsF3Bikf57KCQL/mYjrHtXFBpEO7leA/rDjdH1Ibh7lMbq4AhtXFf1aCr7QsmVFZpmfjnCcyi/r1usgaCC1RtGreNb1V9MthXescBk7iUbwgga6V9EAU5MfdNBRgGm5j38/CFc6qlP91tuMX2UAPWOQlUIoCEJ1tq7b6Lyas6TwH/Csx/3iq6yVKkgEC7dl+dY5EW1Nd23oj5Q=="));//signature text
if (IsValid) {
// show the confirmation box.
JOptionPane.showMessageDialog(this,"Signature is Valid");
} else {
// User canceled signing
JOptionPane.showMessageDialog(this,"Signature is not Valid");
}
}
finally {
mVerifyButton.setLabel(oldButtonLabel);
mVerifyButton.setEnabled(true);
}
//boolean IsValid = verifySig(fileName.getBytes(),,)
// Perform the actual file signing
//CertificationChainAndSignatureBase64 signingResult = signFile(fileName);
}
catch (DocumentSignException dse) {
// Document signing failed. Display error message
String errorMessage = dse.getMessage();
JOptionPane.showMessageDialog(this, errorMessage);
}
catch (SecurityException se) {
se.printStackTrace();
JOptionPane.showMessageDialog(this,
"Unable to access the local file system.\n" +
"This applet should be started with full security permissions.\n" +
"Please accept to trust this applet when the Java Plug-In ask you.");
}
/* catch (JSException jse) {
jse.printStackTrace();
JOptionPane.showMessageDialog(this,
"Unable to access some of the fields of the\n" +
"HTML form. Please check the applet parameters.");
}*/
catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this, "Unexpected error: " + e.getMessage());
}
}
/**
* Signs given local file. The certificate and private key to be used for signing
* come from the locally attached smart card. The user is requested to provide a
* PKCS#11 implementation library and the PIN code for accessing the smart card.
* @param aFileName the name of the file to be signed.
* @return the digital signature of the given file and the certification chain of
* the certificatie used for signing the file, both Base64-encoded or null if the
* signing process is canceled by the user.
* @throws DocumentSignException when a problem arised during the singing process
* (e.g. smart card access problem, invalid certificate, invalid PIN code, etc.)
*/
private CertificationChainAndSignatureBase64 signFile(String aFileName)
throws DocumentSignException {
// Load the file for signing
byte[] documentToSign = null;
try {
documentToSign = aFileName.getBytes();
//documentToSign = readFileInByteArray(aFileName);
} catch (Exception ioex) {
String errorMessage = "There is no text to be signed.";
throw new DocumentSignException(errorMessage, ioex);
}
// Show a dialog for choosing PKCS#11 implementation library and smart card PIN
PKCS11LibraryFileAndPINCodeDialog pkcs11Dialog =
new PKCS11LibraryFileAndPINCodeDialog();
boolean dialogConfirmed;
try {
dialogConfirmed = pkcs11Dialog.run();
} finally {
pkcs11Dialog.dispose();
}
if (dialogConfirmed) {
String oldButtonLabel = mSignButton.getLabel();
mSignButton.setLabel("Working...");
mSignButton.setEnabled(false);
try {
//String pkcs11LibraryFileName = pkcs11Dialog.getLibraryFileName();
//String pkcs11LibraryFileName = "C:\\WINDOWS\\system32\\WatchData\\Egypt Trust CSP V1.0\\WDPKCS.dll";
String winPath = System.getenv("windir");
String pkcs11LibraryFileName = "C:\\Program Files\\Softlock Smart Token Admin\\SLSTSDK.dll";
String pinCode = pkcs11Dialog.getSmartCardPINCode();
// Do the actual signing of the document with the smart card
CertificationChainAndSignatureBase64 signingResult =
signDocument(documentToSign, pkcs11LibraryFileName, pinCode);
return signingResult;
} finally {
mSignButton.setLabel(oldButtonLabel);
mSignButton.setEnabled(true);
}
}
else {
return null;
}
}
private CertificationChainAndSignatureBase64 signDocument(
byte[] aDocumentToSign, String aPkcs11LibraryFileName, String aPinCode)
throws DocumentSignException {
if (aPkcs11LibraryFileName.length() == 0) {
String errorMessage = "It is mandatory to choose a PCKS#11 native " +
"implementation library for smart card (.dll or .so file)!";
throw new DocumentSignException(errorMessage);
}
// Load the keystore from the smart card using the specified PIN code
KeyStore userKeyStore = null;
try {
userKeyStore = loadKeyStoreFromSmartCard(aPkcs11LibraryFileName, aPinCode);
} catch (Exception ex) {
String errorMessage = "Can not read the keystore from the smart card.\n" +
"Possible reasons:\n" +
" - The smart card reader in not connected.\n" +
" - The smart card is not inserted.\n" +
" - The PKCS#11 implementation library is invalid.\n" +
" - The PIN for the smart card is incorrect.\n" +
"Problem details: " + ex.getMessage();
throw new DocumentSignException(errorMessage, ex);
}
// Get the private key and its certification chain from the keystore
PrivateKeyAndCertChain privateKeyAndCertChain = null;
try {
privateKeyAndCertChain =
getPrivateKeyAndCertChain(userKeyStore);
} catch (GeneralSecurityException gsex) {
String errorMessage = "Can not extract the private key and " +
"certificate from the smart card. Reason: " + gsex.getMessage();
throw new DocumentSignException(errorMessage, gsex);
}
// Check if the private key is available
PrivateKey privateKey = privateKeyAndCertChain.mPrivateKey;
if (privateKey == null) {
String errorMessage = "Can not find the private key on the smart card.";
throw new DocumentSignException(errorMessage);
}
// Check if X.509 certification chain is available
Certificate[] certChain = privateKeyAndCertChain.mCertificationChain;
if (certChain == null) {
String errorMessage = "Can not find the certificate on the smart card.";
throw new DocumentSignException(errorMessage);
}
// Create the result object
CertificationChainAndSignatureBase64 signingResult =
new CertificationChainAndSignatureBase64();
// Save X.509 certification chain in the result encoded in Base64
try {
signingResult.mCertificationChain = encodeX509CertChainToBase64(certChain);
}
catch (CertificateException cee) {
String errorMessage = "Invalid certificate on the smart card.";
throw new DocumentSignException(errorMessage);
}
// Calculate the digital signature of the file,
// encode it in Base64 and save it in the result
try {
byte[] digitalSignature = signDocument(aDocumentToSign, privateKey);
signingResult.mSignature = Base64Utils.base64Encode(digitalSignature);
} catch (GeneralSecurityException gsex) {
String errorMessage = "Text signing failed.\n" +
"Problem details: " + gsex.getMessage();
throw new DocumentSignException(errorMessage, gsex);
}
return signingResult;
}
/**
* Loads the keystore from the smart card using its PKCS#11 implementation
* library and the Sun PKCS#11 security provider. The PIN code for accessing
* the smart card is required.
*/
private KeyStore loadKeyStoreFromSmartCard(String aPKCS11LibraryFileName,
String aSmartCardPIN)
throws GeneralSecurityException, IOException {
// First configure the Sun PKCS#11 provider. It requires a stream (or file)
// containing the configuration parameters - "name" and "library".
/* String pkcs11ConfigSettings =
"name = SmartCard\n" + "library = " + aPKCS11LibraryFileName;
byte[] pkcs11ConfigBytes = pkcs11ConfigSettings.getBytes();*/
StringBuffer cardConfig=new StringBuffer();
// cardConfig.append ("slot=0 \n");
cardConfig.append ("name=SmartCard \n");
String winPath = System.getenv("windir");
String libPath = "library=C:\\Program Files\\Softlock Smart Token Admin\\SLSTSDK.dll \n";
//String libPath = "library="+ winPath + "\\system32\\WatchData\\Egypt Trust CSP V1.0\\WDPKCS.dll \n";
//cardConfig.append ("library=C:\\WINDOWS\\system32\\ngp11v211.dll \n");
//cardConfig.append("library=C:\\WINDOWS\\system32\\es1b3k.dll \n");
//cardConfig.append ("library=C:\\WINDOWS\\system32\\aetpkss1.dll \n"); //idependant
// cardConfig.append ("library=C:\\WINDOWS\\system32\\SLSTPKCS11.dll \n"); //--- softlock without finger;
// cardConfig.append ("library=C:\\WINDOWS\\system32\\WatchData\\Egypt Trust CSP V1.0\\WDPKCS.dll \n");
cardConfig.append (libPath);
// cardConfig.append ("library=C:\\Program Files\\Feitian\\ePass1000 SDK V4.2\\PKI\\Lib\\ep1pk111.dll \n");
ByteArrayInputStream confStream = new ByteArrayInputStream(cardConfig.toString().getBytes());
// Instantiate the provider dynamically with Java reflection
try {
Class sunPkcs11Class = Class.forName(SUN_PKCS11_PROVIDER_CLASS);
Constructor pkcs11Constr = sunPkcs11Class.getConstructor(java.io.InputStream.class);
Provider pkcs11Provider = (Provider) pkcs11Constr.newInstance(confStream);
Security.addProvider(pkcs11Provider);
} catch (Exception e) {
throw new KeyStoreException("Can initialize Sun PKCS#11 security " +
"provider. Reason: " + e.getCause().getMessage());
}
// Read the keystore form the smart card
char[] pin = aSmartCardPIN.toCharArray();
KeyStore keyStore = KeyStore.getInstance(PKCS11_KEYSTORE_TYPE);
keyStore.load(null, pin);
return keyStore;
}
/**
* @return private key and certification chain corresponding to it, extracted from
* given keystore. The keystore is considered to have only one entry that contains
* both certification chain and its corresponding private key. If the keystore has
* no entries, an exception is thrown.
*/
private PrivateKeyAndCertChain getPrivateKeyAndCertChain(
KeyStore aKeyStore)
throws GeneralSecurityException {
Enumeration aliasesEnum = aKeyStore.aliases();
if (aliasesEnum.hasMoreElements()) {
String alias = (String)aliasesEnum.nextElement();
Certificate[] certificationChain = aKeyStore.getCertificateChain(alias);
PrivateKey privateKey = (PrivateKey) aKeyStore.getKey(alias, null);
PrivateKeyAndCertChain result = new PrivateKeyAndCertChain();
result.mPrivateKey = privateKey;
result.mCertificationChain = certificationChain;
return result;
} else {
throw new KeyStoreException("The keystore is empty!");
}
}
/**
* @return Base64-encoded ASN.1 DER representation of given X.509 certification
* chain.
*/
private String encodeX509CertChainToBase64(Certificate[] aCertificationChain)
throws CertificateException {
Certificate cert = aCertificationChain[0];
byte[] certPathEncoded = cert.getEncoded();
//JOptionPane.showMessageDialog(this,aCertificationChain.length);
//List certList = Arrays.asList(aCertificationChain);
//CertificateFactory certFactory =
// CertificateFactory.getInstance(X509_CERTIFICATE_TYPE);
//CertPath certPath = certFactory.generateCertPath(certList);
//byte[] certPathEncoded = certPath.getEncoded(CERTIFICATION_CHAIN_ENCODING);
String base64encodedCertChain = Base64Utils.base64Encode(certPathEncoded);
return base64encodedCertChain;
}
/**
* Reads the specified file into a byte array.
*/
private byte[] readFileInByteArray(String aFileName)
throws IOException {
File file = new File(aFileName);
FileInputStream fileStream = new FileInputStream(file);
try {
int fileSize = (int) file.length();
byte[] data = new byte[fileSize];
int bytesRead = 0;
while (bytesRead < fileSize) {
bytesRead += fileStream.read(data, bytesRead, fileSize-bytesRead);
}
return data;
}
finally {
fileStream.close();
}
}
/**
* Signs given document with a given private key.
*/
private byte[] signDocument(byte[] aDocument, PrivateKey aPrivateKey)
throws GeneralSecurityException {
Signature signatureAlgorithm =
Signature.getInstance(DIGITAL_SIGNATURE_ALGORITHM_NAME);
signatureAlgorithm.initSign(aPrivateKey);
signatureAlgorithm.update(aDocument);
byte[] digitalSignature = signatureAlgorithm.sign();
return digitalSignature;
}
/**
* Data structure that holds a pair of private key and
* certification chain corresponding to this private key.
*/
static class PrivateKeyAndCertChain {
public PrivateKey mPrivateKey;
public Certificate[] mCertificationChain;
}
/**
* Data structure that holds a pair of Base64-encoded
* certification chain and digital signature.
*/
static class CertificationChainAndSignatureBase64 {
public String mCertificationChain = null;
public String mSignature = null;
}
/**
* Exception class used for document signing errors.
*/
static class DocumentSignException extends Exception {
public DocumentSignException(String aMessage) {
super(aMessage);
}
public DocumentSignException(String aMessage, Throwable aCause) {
super(aMessage, aCause);
}
}
}
.net version
class Program
{
static void Main2(string[] args)
{
// Creates a Cryptoki object related to the specific PKCS#11 native library
Cryptoki cryptoki = new Cryptoki("SLSTSDK.dll");
cryptoki.Initialize();
// Prints all information relating to the native library
CryptokiInfo info = cryptoki.Info;
Console.WriteLine(info.Version);
Console.WriteLine(info.ManufacturerID);
Console.WriteLine(info.LibDescription);
// Reads the set of slots containing a token
SlotList slots = cryptoki.Slots;
if(slots.Count == 0)
{
Console.WriteLine("No slot available");
return;
}
// Gets the first slot available
Slot slot = slots[0];
// Prints all information relating to the slot
SlotInfo sinfo = slot.Info;
Console.WriteLine(sinfo.Description);
Console.WriteLine(sinfo.ManufacturerID);
if(!slot.IsTokenPresent)
{
Console.WriteLine("No token inserted in the slot: " + slots[0].Info.Description);
return;
}
// Gets the first token available
Token token = slot.Token;
// Prints all information relating to the token
TokenInfo tinfo = token.Info;
Console.WriteLine(tinfo.Label);
Console.WriteLine(tinfo.ManufacturerID);
Console.WriteLine(tinfo.Model);
Console.WriteLine(tinfo.SerialNumber);
Console.WriteLine(tinfo.HardwareVersion);
// Opens a read/write serial session
Session session =
token.OpenSession(Session.CKF_SERIAL_SESSION | Session.CKF_RW_SESSION,
null,
null);
// Executes the login passing the user PIN
int nRes = session.Login(Session.CKU_USER, "12345678");
if (nRes != 0)
{
Console.WriteLine("Wrong PIN");
return;
}
Console.WriteLine("Logged in:" + session.IsLoggedIn);
// Searchs for an RSA private key object
// Sets the template with its attributes
CryptokiCollection template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PRIVATE_KEY));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, "Ugo's new Key"));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_TOKEN, true));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_PRIVATE, true));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_MODIFIABLE, true));
// Launchs the search specifying the template just created
CryptokiCollection objects = session.Objects.Find(template, 10);
foreach (Object obj in objects)
{
Console.WriteLine(((PrivateKey)obj).Label);
}
for (int i = 0; i < objects.Count; i++)
{
Console.WriteLine(((PrivateKey)objects[i]).Label);
}
RSAPrivateKey privateKey;
RSAPublicKey publicKey;
// If the private key is not found generates the key pair
if(objects.Count == 0)
{
CryptokiCollection templatePub = new CryptokiCollection();
templatePub.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PUBLIC_KEY));
templatePub.Add(new ObjectAttribute(ObjectAttribute.CKA_TOKEN, true));
templatePub.Add(new ObjectAttribute(ObjectAttribute.CKA_PRIVATE, true));
templatePub.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, "Ugo's new Key"));
templatePub.Add(new ObjectAttribute(ObjectAttribute.CKA_ID, "1"));
templatePub.Add(new ObjectAttribute(ObjectAttribute.CKA_MODULUS_BITS, 1024));
CryptokiCollection templatePri = new CryptokiCollection();
templatePri.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PRIVATE_KEY));
templatePri.Add(new ObjectAttribute(ObjectAttribute.CKA_TOKEN, true));
templatePri.Add(new ObjectAttribute(ObjectAttribute.CKA_PRIVATE, true));
templatePri.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, "Ugo's new Key"));
templatePri.Add(new ObjectAttribute(ObjectAttribute.CKA_ID, "1"));
//Generate the key pair
Key[] keys = session.GenerateKeyPair(Mechanism.RSA_PKCS_KEY_PAIR_GEN, templatePub, templatePri);
privateKey = (RSAPrivateKey)keys[1];
publicKey = (RSAPublicKey)keys[0];
objects = session.Objects.Find(template, 1);
Console.WriteLine(publicKey.Label);
// prepares for the signature
string helloworld = "test";
//System.Text.UTF8Encoding
byte[] text = System.Text.Encoding.UTF8.GetBytes(helloworld);
// launches the digital signature operation with a RSA_PKCS mechanism
nRes = session.SignInit(Mechanism.SHA1_RSA_PKCS, privateKey);
// computes the signature
byte[] signature = session.Sign(text);
string aa = Convert.ToBase64String(signature);
Console.WriteLine("key is : " + aa);
// launches the digital signature verification with a RSA_PKCS mechanism
nRes = session.VerifyInit(Mechanism.SHA1_RSA_PKCS, publicKey);
// verifies the signature
nRes = session.Verify(text, signature);
// results if nRes == 0 means that the verification is OK
Console.Write("Verified " + (nRes == 0));
}
else //If the private key is found gets the corresponding public key
{
privateKey = (RSAPrivateKey)objects[objects.Count - 1];
Console.WriteLine(privateKey.Label);
// search for the related public key
template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PUBLIC_KEY));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, "Ugo's new Key"));
// Launchs the search specifying the template just created
objects = session.Objects.Find(template, 1);
publicKey = (RSAPublicKey)objects[0];
Console.WriteLine(publicKey.Label);
// prepares for the signature
string helloworld = "test";
//System.Text.UTF8Encoding
byte[] text = System.Text.Encoding.UTF8.GetBytes(helloworld);
//X509Certificate2 dd = new X509Certificate2(
// launches the digital signature operation with a RSA_PKCS mechanism
nRes = session.SignInit(Mechanism.SHA1_RSA_PKCS, privateKey);
// computes the signature
byte[] signature = session.Sign(text);
string aa = BitConverter.ToString(signature);
Console.WriteLine("");
Console.WriteLine("key is : " + aa);
// launches the digital signature verification with a RSA_PKCS mechanism
nRes = session.VerifyInit(Mechanism.SHA1_RSA_PKCS, publicKey);
// verifies the signature
nRes = session.Verify(text, signature);
// results if nRes == 0 means that the verification is OK
Console.Write("Verified " + (nRes == 0));
Console.ReadLine();
}
// Logouts and closes the session
session.Logout();
session.Close();
cryptoki.Finalize(IntPtr.Zero);
}
}
Please I appreciate your help as my knowledge
is very li
mited in this area