📄 pkcs11signer.java
字号:
if (getSession() < 0) return -1L; log.println("finding a signature key..."); CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[1]; attributeTemplateList[0] = new CK_ATTRIBUTE(); attributeTemplateList[0].type = PKCS11Constants.CKA_CLASS; attributeTemplateList[0].pValue = new Long( PKCS11Constants.CKO_PRIVATE_KEY); pkcs11Module.C_FindObjectsInit(getSession(), attributeTemplateList); long[] availableSignatureKeys = pkcs11Module.C_FindObjects( getSession(), 100); //maximum of 100 at once if (availableSignatureKeys == null) { log.println("null returned - no signature key found"); } else { log.println("found " + availableSignatureKeys.length + " signature keys, picking first."); for (int i = 0; i < availableSignatureKeys.length; i++) { if (i == 0) { // the first we find, we take as our signature key signatureKeyHandle = availableSignatureKeys[i]; log .println("for signing we use signature key with handle: " + signatureKeyHandle); } } } pkcs11Module.C_FindObjectsFinal(getSession()); return signatureKeyHandle; } /** * Sign (here means encrypting with private key) the provided data with a * single operation. This is the only modality supported by the (currently * fixed) RSA_PKCS mechanism. * * @param signatureKeyHandle * handle of the private key to use for signing. * @param data * the data to sign. * @return a byte[] containing signed data. * @throws IOException * @throws PKCS11Exception */ public byte[] signDataSinglePart(long signatureKeyHandle, byte[] data) throws IOException, PKCS11Exception { byte[] signature = null; if (getSession() < 0) return null; System.out.println("\nStart single part sign operation..."); pkcs11Module.C_SignInit(getSession(), this.signatureMechanism, signatureKeyHandle); if ((data.length > 0) && (data.length < 1024)) { System.out.println("Signing ..."); signature = pkcs11Module.C_Sign(getSession(), data); System.out.println("FINISHED."); } else System.out.println("Error in data length!"); return signature; } /** * Sign (here means digesting and encrypting with private key) the provided * data with a multiple-pass operation. This is the a modality supported by * CKM_SHA1_RSA_PKCS, for example, that digests and ecrypts data. Note that * some Infocamere card-cryptoki combinations does not supports this type of * mechanisms. * * @param signatureKeyHandle * handle of the private key to use for signing. * @param dataStream * an <code>InputStram</code> providing data to sign. * @return a byte[] containing signed data. * @throws IOException * @throws PKCS11Exception */ public byte[] signDataMultiplePart(long signatureKeyHandle, InputStream dataStream) throws IOException, PKCS11Exception { byte[] signature = null; byte[] buffer = new byte[1024]; byte[] helpBuffer; int bytesRead; System.out.println("\nStart multiple part sign operation..."); pkcs11Module.C_SignInit(getSession(), this.signatureMechanism, signatureKeyHandle); while ((bytesRead = dataStream.read(buffer, 0, buffer.length)) >= 0) { helpBuffer = new byte[bytesRead]; // we need a buffer that only holds what to send for signing System.arraycopy(buffer, 0, helpBuffer, 0, bytesRead); System.out.println("Byte letti: " + bytesRead); pkcs11Module.C_SignUpdate(getSession(), helpBuffer); Arrays.fill(helpBuffer, (byte) 0); } Arrays.fill(buffer, (byte) 0); signature = pkcs11Module.C_SignFinal(getSession()); return signature; } // look for a RSA key and encrypt ... public byte[] encryptDigest(String label, byte[] digest) throws PKCS11Exception, IOException { byte[] encryptedDigest = null; long sessionHandle = getSession(); if (sessionHandle < 0) return null; long signatureKeyHandle = findSignatureKeyFromLabel(label); if (signatureKeyHandle > 0) { log.println("\nStarting digest encryption..."); encryptedDigest = signDataSinglePart(signatureKeyHandle, digest); } else { // we have not found a suitable key, we cannot contiue } return encryptedDigest; } /** * Queries the a specific token for a certificate suitable for a legal value * subscription. See * {@link PKCS11Signer#findCertificateWithNonRepudiationCritical()}. * * @see findCertificateWithNonRepudiationCritical() * * @param token * ID of the token to query for the certificate. * @return the handle of the required certificate, if found; -1 otherwise. * @throws TokenException * @throws CertificateException */ public long findCertificateWithNonRepudiationCritical(long token) throws TokenException, CertificateException { long certKeyHandle = -1L; long s = openSession(token); if (s == -1L) { log.println("Unable to open a session on token with handle: " + token); return -1L; } log.println("finding a certificate with " + "Critical KeyUsage including non repudiation\n" + " on token with handle: " + token); CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[1]; attributeTemplateList[0] = new CK_ATTRIBUTE(); attributeTemplateList[0].type = PKCS11Constants.CKA_CLASS; attributeTemplateList[0].pValue = new Long( PKCS11Constants.CKO_CERTIFICATE); pkcs11Module.C_FindObjectsInit(s, attributeTemplateList); long[] availableCertificates = pkcs11Module.C_FindObjects(s, 100); //maximum of 100 at once pkcs11Module.C_FindObjectsFinal(s); if (availableCertificates == null) { log.println("null returned - no certificate key found"); } else { log.println("found " + availableCertificates.length + " certificates"); byte[] certBytes = null; java.security.cert.X509Certificate javaCert = null; java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory .getInstance("X.509"); java.io.ByteArrayInputStream bais = null; for (int i = 0; (i < availableCertificates.length) && (certKeyHandle < 0); i++) { log.println("Checking KeyUsage for certificate with handle: " + availableCertificates[i]); certBytes = getDEREncodedCertificate(availableCertificates[i], s); bais = new java.io.ByteArrayInputStream(certBytes); javaCert = (java.security.cert.X509Certificate) cf .generateCertificate(bais); if (isKeyUsageNonRepudiationCritical(javaCert)) { certKeyHandle = availableCertificates[i]; log.println("Check OK!"); } else log.println("Check failed."); } } closeSession(s); return certKeyHandle; } /** * Queries the current token for a certificate suitable for a legal value * subscription. * <p> * According to the italian law, if you want give to the digital signature * the maximum legal value (equivalent to a signature on paper), and also * for the sake of interoperability, the signer certificate has to satisfy * some costraints. See <a * href="http://www.cnipa.gov.it/site/_contentfiles/00127900/127910_CR%2024_2000.pdf"> * the official document in PDF format <a>or <a * href="http://www.interlex.it/testi/interop.htm"> this html page <a>(only * in italian, sorry) for details. * <p> * In particular, the certificate has to carry a KeyUsage extension of 'non * repudiation' (OID: 2.5.29.15) marked as critical. * * * @return the handle of the required certificate, if found; -1 otherwise. * @throws TokenException * @throws CertificateException */ public long findCertificateWithNonRepudiationCritical() throws TokenException, CertificateException { long certKeyHandle = -1L; if (getSession() < 0) return -1L; log .println("finding a certificate with Critical KeyUsage including non repudiation ..."); CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[1]; attributeTemplateList[0] = new CK_ATTRIBUTE(); attributeTemplateList[0].type = PKCS11Constants.CKA_CLASS; attributeTemplateList[0].pValue = new Long( PKCS11Constants.CKO_CERTIFICATE); pkcs11Module.C_FindObjectsInit(getSession(), attributeTemplateList); long[] availableCertificates = pkcs11Module.C_FindObjects(getSession(), 100); //maximum of 100 at once pkcs11Module.C_FindObjectsFinal(getSession()); if (availableCertificates == null) { log.println("null returned - no certificate key found"); } else { log.println("found " + availableCertificates.length + " certificates"); byte[] certBytes = null; java.security.cert.X509Certificate javaCert = null; java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory .getInstance("X.509"); java.io.ByteArrayInputStream bais = null; for (int i = 0; (i < availableCertificates.length) && (certKeyHandle < 0); i++) { log.println("Checking KeyUsage for certificate with handle: " + availableCertificates[i]); certBytes = getDEREncodedCertificate(availableCertificates[i]); bais = new java.io.ByteArrayInputStream(certBytes); javaCert = (java.security.cert.X509Certificate) cf .generateCertificate(bais); if (isKeyUsageNonRepudiationCritical(javaCert)) { certKeyHandle = availableCertificates[i]; log.println("Check OK!"); } else log.println("Check failed."); } } return certKeyHandle; } /** * checks Key Usage constraints of a java certificate. * * @param javaCert * the certificate to check as java object. * @return true if the given certificate has a KeyUsage extension of 'non * repudiation' (OID: 2.5.29.15) marked as critical. * @see PKCS11Signer#findCertificateWithNonRepudiationCritical() */ boolean isKeyUsageNonRepudiationCritical( java.security.cert.X509Certificate javaCert) { boolean isNonRepudiationPresent = false; boolean isKeyUsageCritical = false; Set oids = javaCert.getCriticalExtensionOIDs(); if (oids != null) // check presence between critical extensions of oid:2.5.29.15 // (KeyUsage) isKeyUsageCritical = oids.contains("2.5.29.15"); boolean[] keyUsages = javaCert.getKeyUsage(); if (keyUsages != null) //check non repudiation (index 1) isNonRepudiationPresent = keyUsages[1]; return (isKeyUsageCritical && isNonRepudiationPresent); } /** * Finds a certificate matching the given byte[] id. * * @param id * @return the handle of the certificate, or -1 if not found. * @throws PKCS11Exception */ public long findCertificateFromID(byte[] id) throws PKCS11Exception { long sessionHandle = getSession();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -