Java tutorial
/************************************************************************* * * * SignServer: The OpenSource Automated Signing Server * * * * This software is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or any later version. * * * * See terms of license at gnu.org. * * * *************************************************************************/ package org.signserver.server.cryptotokens; import org.bouncycastle.jce.X509Principal; import org.bouncycastle.x509.X509V3CertificateGenerator; import org.cesecore.keys.token.*; import org.signserver.common.*; import java.io.*; import java.math.BigInteger; import java.security.*; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.util.*; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; import org.cesecore.keys.token.p11.exception.NoSuchSlotException; import org.cesecore.util.query.QueryCriteria; import static org.signserver.server.BaseProcessable.PROPERTY_CACHE_PRIVATEKEY; import org.signserver.common.CryptoTokenOfflineException; import org.signserver.server.ExceptionUtil; import org.signserver.server.IServices; import sun.security.x509.*; import javax.crypto.*; /** * CryptoToken implementation wrapping the new PKCS11CryptoToken from CESeCore. * * Note: The mapping between SignServer APIs and CESeCore is not perfect. In * particular the SignServer calls for testing and generating key-pairs takes * an authentication code while the CESeCore ones assumes the token is already * activated. This means that the auth code parameter will be ignored for those * methods. * * @author Markus Kils * @version $Id: PKCS11CryptoToken.java 6150 2015-07-17 13:41:56Z netmackan $ */ public class PKCS11CryptoToken extends BaseCryptoToken { private static final Logger LOG = Logger.getLogger(PKCS11CryptoToken.class); private final KeyStorePKCS11CryptoToken delegate; public PKCS11CryptoToken() throws InstantiationException { delegate = new KeyStorePKCS11CryptoToken(); } private String keyAlias; private String nextKeyAlias; private boolean cachePrivateKey; private PrivateKey cachedPrivateKey; // cached P11 library definitions (defined at deploy-time) private PKCS11Settings settings; private Integer keygenerationLimit; @Override public void init(int workerId, Properties props) throws CryptoTokenInitializationFailureException { try { final String attributesValue = props.getProperty(CryptoTokenHelper.PROPERTY_ATTRIBUTES); if (attributesValue != null && props.getProperty(CryptoTokenHelper.PROPERTY_ATTRIBUTESFILE) != null) { throw new CryptoTokenInitializationFailureException( "Only specify one of " + CryptoTokenHelper.PROPERTY_ATTRIBUTES + " and " + CryptoTokenHelper.PROPERTY_ATTRIBUTESFILE); } if (attributesValue != null) { OutputStream out = null; try { File attributesFile = File.createTempFile("attributes-" + workerId + "-", ".tmp"); if (LOG.isDebugEnabled()) { LOG.debug("Created attributes file: " + attributesFile.getAbsolutePath()); } attributesFile.deleteOnExit(); out = new FileOutputStream(attributesFile); IOUtils.write(attributesValue, out); props.setProperty(CryptoTokenHelper.PROPERTY_ATTRIBUTESFILE, attributesFile.getAbsolutePath()); } catch (IOException ex) { throw new CryptoTokenInitializationFailureException("Unable to create attributes file", ex); } finally { IOUtils.closeQuietly(out); } } // Check that both the new or the legacy properties are specified at the same time if (props.getProperty(CryptoTokenHelper.PROPERTY_SLOT) != null && props.getProperty(CryptoTokenHelper.PROPERTY_SLOTLABELVALUE) != null) { throw new CryptoTokenInitializationFailureException("Can not specify both " + CryptoTokenHelper.PROPERTY_SLOT + " and " + CryptoTokenHelper.PROPERTY_SLOTLABELVALUE); } if (props.getProperty(CryptoTokenHelper.PROPERTY_SLOTLISTINDEX) != null && props.getProperty(CryptoTokenHelper.PROPERTY_SLOTLABELVALUE) != null) { throw new CryptoTokenInitializationFailureException( "Can not specify both " + CryptoTokenHelper.PROPERTY_SLOTLISTINDEX + " and " + CryptoTokenHelper.PROPERTY_SLOTLABELVALUE); } props = CryptoTokenHelper.fixP11Properties(props); final String sharedLibraryName = props.getProperty("sharedLibraryName"); final String sharedLibraryProperty = props.getProperty("sharedLibrary"); settings = PKCS11Settings.getInstance(); // at least one the SHAREDLIBRARYNAME or SHAREDLIBRAY // (for backwards compatability) properties must be defined if (sharedLibraryName == null && sharedLibraryProperty == null) { final StringBuilder sb = new StringBuilder(); sb.append("Missing SHAREDLIBRARYNAME property\n"); settings.listAvailableLibraryNames(sb); throw new CryptoTokenInitializationFailureException(sb.toString()); } // if only the old SHAREDLIBRARY property is given, it must point // to one of the libraries defined at deploy-time if (sharedLibraryProperty != null && sharedLibraryName == null) { // check if the library was defined at deploy-time if (!settings.isP11LibraryExisting(sharedLibraryProperty)) { throw new CryptoTokenInitializationFailureException( "SHAREDLIBRARY is not permitted when pointing to a library not defined at deploy-time"); } } // lookup the library defined by SHAREDLIBRARYNAME among the // deploy-time-defined values final String sharedLibraryFile = sharedLibraryName == null ? null : settings.getP11SharedLibraryFileForName(sharedLibraryName); // both the old and new properties are allowed at the same time // to ease migration, given that they point to the same library if (sharedLibraryProperty != null && sharedLibraryName != null) { if (sharedLibraryFile != null) { final File byPath = new File(sharedLibraryProperty); final File byName = new File(sharedLibraryFile); try { if (!byPath.getCanonicalPath().equals(byName.getCanonicalPath())) { // the properties pointed to different libraries throw new CryptoTokenInitializationFailureException( "Can not specify both SHAREDLIBRARY and SHAREDLIBRARYNAME at the same time"); } } catch (IOException e) { // failed to determine canonical paths, treat this as conflicting properties throw new CryptoTokenInitializationFailureException( "Can not specify both SHAREDLIBRARY and SHAREDLIBRARYNAME at the same time"); } } else { // could not associate SHAREDLIBRARYNAME with a path, treat this as conflicting properties throw new CryptoTokenInitializationFailureException( "Can not specify both SHAREDLIBRARY and SHAREDLIBRARYNAME at the same time"); } } // if only SHAREDLIBRARYNAME was given and the value couldn't be // found, include a list of available values in the token error // message if (sharedLibraryFile == null && sharedLibraryProperty == null) { final StringBuilder sb = new StringBuilder(); sb.append("SHAREDLIBRARYNAME "); sb.append(sharedLibraryName); sb.append(" is not referring to a defined value"); sb.append("\n"); settings.listAvailableLibraryNames(sb); throw new CryptoTokenInitializationFailureException(sb.toString()); } // check the file (again) and pass it on to the underlaying implementation if (sharedLibraryFile != null) { final File sharedLibrary = new File(sharedLibraryFile); if (!sharedLibrary.isFile() || !sharedLibrary.canRead()) { throw new CryptoTokenInitializationFailureException( "The shared library file can't be read: " + sharedLibrary.getAbsolutePath()); } // propagate the shared library property to the delegate props.setProperty("sharedLibrary", sharedLibraryFile); } final String slotLabelType = props.getProperty(CryptoTokenHelper.PROPERTY_SLOTLABELTYPE); if (slotLabelType == null) { throw new CryptoTokenInitializationFailureException( "Missing " + CryptoTokenHelper.PROPERTY_SLOTLABELTYPE + " property"); } final String slotLabelValue = props.getProperty(CryptoTokenHelper.PROPERTY_SLOTLABELVALUE); if (slotLabelValue == null) { throw new CryptoTokenInitializationFailureException( "Missing " + CryptoTokenHelper.PROPERTY_SLOTLABELVALUE + " property"); } delegate.init(props, null, workerId); keyAlias = props.getProperty("defaultKey"); nextKeyAlias = props.getProperty("nextCertSignKey"); cachePrivateKey = Boolean .parseBoolean(props.getProperty(PROPERTY_CACHE_PRIVATEKEY, Boolean.FALSE.toString())); if (LOG.isDebugEnabled()) { final StringBuilder sb = new StringBuilder(); sb.append("keyAlias: ").append(keyAlias).append("\n"); sb.append("nextKeyAlias: ").append(nextKeyAlias).append("\n"); sb.append("cachePrivateKey: ").append(cachePrivateKey); LOG.debug(sb.toString()); } // Read property KEYGENERATIONLIMIT final String keygenLimitValue = props.getProperty(CryptoTokenHelper.PROPERTY_KEYGENERATIONLIMIT); if (keygenLimitValue != null && !keygenLimitValue.trim().isEmpty()) { try { keygenerationLimit = Integer.parseInt(keygenLimitValue.trim()); } catch (NumberFormatException ex) { throw new CryptoTokenInitializationFailureException("Incorrect value for " + CryptoTokenHelper.PROPERTY_KEYGENERATIONLIMIT + ": " + ex.getLocalizedMessage()); } } } catch (org.cesecore.keys.token.CryptoTokenOfflineException ex) { LOG.error("Init failed", ex); throw new CryptoTokenInitializationFailureException(ex.getMessage()); } catch (NoSuchSlotException ex) { LOG.error("Slot not found", ex); throw new CryptoTokenInitializationFailureException(ex.getMessage()); } catch (NumberFormatException ex) { LOG.error("Init failed", ex); throw new CryptoTokenInitializationFailureException(ex.getMessage()); } } @Override public int getCryptoTokenStatus(IServices services) { return getCryptoTokenStatus(); } @Override public int getCryptoTokenStatus() { int result = delegate.getTokenStatus(); if (result == WorkerStatus.STATUS_ACTIVE) { result = WorkerStatus.STATUS_OFFLINE; try { if (LOG.isDebugEnabled()) { final StringBuilder sb = new StringBuilder(); sb.append("keyAlias: ").append(keyAlias).append("\n"); sb.append("nextKeyAlias: ").append(nextKeyAlias).append("\n"); LOG.debug(sb.toString()); } for (String testKey : new String[] { keyAlias, nextKeyAlias }) { if (testKey != null && !testKey.isEmpty()) { PrivateKey privateKey = delegate.getPrivateKey(testKey); if (privateKey != null) { PublicKey publicKey = delegate.getPublicKey(testKey); CryptoTokenHelper.testSignAndVerify(privateKey, publicKey, delegate.getSignProviderName()); result = WorkerStatus.STATUS_ACTIVE; } } } } catch (org.cesecore.keys.token.CryptoTokenOfflineException ex) { LOG.error("Error testing activation", ex); } catch (NoSuchAlgorithmException ex) { LOG.error("Error testing activation", ex); } catch (NoSuchProviderException ex) { LOG.error("Error testing activation", ex); } catch (InvalidKeyException ex) { LOG.error("Error testing activation", ex); } catch (SignatureException ex) { LOG.error("Error testing activation", ex); } } return result; } @Override public void activate(String authenticationcode) throws CryptoTokenAuthenticationFailureException, CryptoTokenOfflineException { try { delegate.activate(authenticationcode.toCharArray()); } catch (org.cesecore.keys.token.CryptoTokenOfflineException ex) { LOG.error("Activate failed", ex); throw new CryptoTokenOfflineException(ex); } catch (CryptoTokenAuthenticationFailedException ex) { final StringBuilder sb = new StringBuilder(); sb.append("Activate failed"); for (final String causeMessage : ExceptionUtil.getCauseMessages(ex)) { sb.append(": "); sb.append(causeMessage); } LOG.error(sb.toString()); throw new CryptoTokenAuthenticationFailureException(sb.toString()); } } @Override public boolean deactivate() throws CryptoTokenOfflineException { delegate.deactivate(); return true; } @Override public PrivateKey getPrivateKey(int purpose) throws CryptoTokenOfflineException { final PrivateKey result; if (purpose == ICryptoToken.PURPOSE_NEXTKEY) { result = getPrivateKey(nextKeyAlias); } else { if (cachePrivateKey && cachedPrivateKey != null) { result = cachedPrivateKey; } else { result = getPrivateKey(keyAlias); if (cachePrivateKey) { cachedPrivateKey = result; } } } return result; } @Override public PublicKey getPublicKey(int purpose) throws CryptoTokenOfflineException { final String alias = purpose == ICryptoToken.PURPOSE_NEXTKEY ? nextKeyAlias : keyAlias; return getPublicKey(alias); } @Override public PrivateKey getPrivateKey(String alias) throws CryptoTokenOfflineException { try { return delegate.getPrivateKey(alias); } catch (org.cesecore.keys.token.CryptoTokenOfflineException ex) { throw new CryptoTokenOfflineException(ex); } } @Override public PublicKey getPublicKey(String alias) throws CryptoTokenOfflineException { try { return delegate.getPublicKey(alias); } catch (org.cesecore.keys.token.CryptoTokenOfflineException ex) { throw new CryptoTokenOfflineException(ex); } } @Override public String getProvider(int providerUsage) { return delegate.getSignProviderName(); } @Override public Certificate getCertificate(int purpose) throws CryptoTokenOfflineException { final String alias = purpose == ICryptoToken.PURPOSE_NEXTKEY ? nextKeyAlias : keyAlias; return getCertificate(alias); } @Override public List<Certificate> getCertificateChain(int purpose) throws CryptoTokenOfflineException { final String alias = purpose == ICryptoToken.PURPOSE_NEXTKEY ? nextKeyAlias : keyAlias; return getCertificateChain(alias); } @Override public Certificate getCertificate(String alias) throws CryptoTokenOfflineException { try { Certificate result = delegate.getActivatedKeyStore().getCertificate(alias); // Do not return the dummy certificate if (CryptoTokenHelper.isDummyCertificate(result)) { result = null; } return result; } catch (KeyStoreException ex) { throw new CryptoTokenOfflineException(ex); } } @Override public List<Certificate> getCertificateChain(String alias) throws CryptoTokenOfflineException { try { final List<Certificate> result; final Certificate[] certChain = delegate.getActivatedKeyStore().getCertificateChain(alias); if (certChain == null || (certChain.length == 1 && CryptoTokenHelper.isDummyCertificate(certChain[0]))) { result = null; } else { result = Arrays.asList(certChain); } return result; } catch (KeyStoreException ex) { throw new CryptoTokenOfflineException(ex); } } @Override public ICertReqData genCertificateRequest(ISignerCertReqInfo info, final boolean explicitEccParameters, boolean defaultKey) throws CryptoTokenOfflineException { if (LOG.isDebugEnabled()) { LOG.debug("defaultKey: " + defaultKey); } final String alias; if (defaultKey) { alias = keyAlias; } else { alias = nextKeyAlias; } return genCertificateRequest(info, explicitEccParameters, alias); } @Override public ICertReqData genCertificateRequest(ISignerCertReqInfo info, final boolean explicitEccParameters, String alias) throws CryptoTokenOfflineException { if (LOG.isDebugEnabled()) { LOG.debug(">genCertificateRequest CESeCorePKCS11CryptoToken"); LOG.debug("alias: " + alias); } try { return CryptoTokenHelper.genCertificateRequest(info, delegate.getPrivateKey(alias), getProvider(ICryptoToken.PROVIDERUSAGE_SIGN), delegate.getPublicKey(alias), explicitEccParameters); } catch (org.cesecore.keys.token.CryptoTokenOfflineException e) { LOG.error("Certificate request error: " + e.getMessage(), e); throw new CryptoTokenOfflineException(e); } catch (IllegalArgumentException ex) { if (LOG.isDebugEnabled()) { LOG.error("Certificate request error", ex); } throw new CryptoTokenOfflineException(ex.getMessage(), ex); } } /** * Method not supported. */ @Override public boolean destroyKey(int purpose) { return false; } @Override public byte[] decryptByteData(String alias, String authcode, byte[] encryptedData, IServices services) throws NoSuchAlgorithmException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, CryptoTokenOfflineException, UnrecoverableKeyException, KeyStoreException, InvalidKeyException, IOException, ShortBufferException { return decryptByteData(alias, authcode, encryptedData); } @Override public byte[] decryptByteData(String alias, String pin, byte[] encryptedData) throws NoSuchPaddingException, NoSuchAlgorithmException, CryptoTokenOfflineException, UnrecoverableKeyException, KeyStoreException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException, ShortBufferException { Cipher decrypt = Cipher.getInstance("RSA/ECB/PKCS1Padding"); PrivateKey privateKey = (PrivateKey) delegate.getActivatedKeyStore().getKey(alias, pin.toCharArray()); decrypt.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedDataBytes = cryptDataBytes(decrypt, encryptedData, false); return decryptedDataBytes; } @Override public byte[] encryptMessage(String alias, String authcode, byte[] message, IServices services) throws NoSuchAlgorithmException, NoSuchPaddingException, org.cesecore.keys.token.CryptoTokenOfflineException, InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException, ShortBufferException { return encryptMessage(alias, authcode, message); } @Override public byte[] encryptMessage(String alias, String authcode, byte[] message) throws NoSuchPaddingException, NoSuchAlgorithmException, org.cesecore.keys.token.CryptoTokenOfflineException, InvalidKeyException, IOException, BadPaddingException, IllegalBlockSizeException, ShortBufferException { Cipher encrypt = Cipher.getInstance("RSA/ECB/PKCS1Padding"); encrypt.init(Cipher.ENCRYPT_MODE, delegate.getPublicKey(alias)); byte[] encryptedBytes = cryptDataBytes(encrypt, message, true); return encryptedBytes; } @Override public boolean removeKey(String alias) throws CryptoTokenOfflineException, KeyStoreException, SignServerException { return CryptoTokenHelper.removeKey(getKeyStore(), alias); } @Override public Collection<KeyTestResult> testKey(String alias, char[] authCode) throws CryptoTokenOfflineException, KeyStoreException { final KeyStore keyStore = delegate.getActivatedKeyStore(); return CryptoTokenHelper.testKey(keyStore, alias, authCode, keyStore.getProvider().getName()); } @Override public Collection<KeyTestResult> testKey(String alias, char[] authCode, IServices services) throws CryptoTokenOfflineException, KeyStoreException { return testKey(alias, authCode); } @Override public KeyStore getKeyStore() throws UnsupportedOperationException, CryptoTokenOfflineException, KeyStoreException { return delegate.getActivatedKeyStore(); } @Override public void generateKey(String keyAlgorithm, String keySpec, String alias, char[] authCode) throws TokenOutOfSpaceException, CryptoTokenOfflineException, IllegalArgumentException { if (keySpec == null) { throw new IllegalArgumentException("Missing keyspec parameter"); } if (alias == null) { throw new IllegalArgumentException("Missing alias parameter"); } if (LOG.isDebugEnabled()) { LOG.debug("keyAlgorithm: " + keyAlgorithm + ", keySpec: " + keySpec + ", alias: " + alias); } // Keyspec for DSA is prefixed with "dsa" if (keyAlgorithm != null && keyAlgorithm.equalsIgnoreCase("DSA") && !keySpec.contains("dsa")) { keySpec = "dsa" + keySpec; } // Check key generation limit, if configured if (keygenerationLimit != null && keygenerationLimit > -1) { final int current; try { current = delegate.getActivatedKeyStore().size(); if (current >= keygenerationLimit) { throw new TokenOutOfSpaceException("Key generation limit exceeded: " + current); } } catch (KeyStoreException ex) { LOG.error("Checking key generation limit failed", ex); throw new TokenOutOfSpaceException( "Current number of key entries could not be obtained: " + ex.getMessage(), ex); } } try { delegate.generateKeyPair(keySpec, alias); } catch (InvalidAlgorithmParameterException ex) { LOG.error(ex, ex); throw new CryptoTokenOfflineException(ex); } catch (org.cesecore.keys.token.CryptoTokenOfflineException ex) { LOG.error(ex, ex); throw new CryptoTokenOfflineException(ex); } } @Override public void generateKey(String keyAlgorithm, String keySpec, String alias, char[] authCode, Map<String, Object> params, IServices services) throws CryptoTokenOfflineException, IllegalArgumentException { generateKey(keyAlgorithm, keySpec, alias, authCode); } @Override public Certificate generateSignerKeyAndGetCertificate(String keyAlgorithm, String keySpec, String alias, char[] authCode) throws TokenOutOfSpaceException, CryptoTokenOfflineException, IllegalArgumentException { generateKey(keyAlgorithm, keySpec, alias, authCode); try { return createSelfSignCertificate(alias, keyAlgorithm, authCode); } catch (SignatureException e) { throw new CryptoTokenOfflineException("Singnature Execption", e); } catch (InvalidKeyException e) { throw new CryptoTokenOfflineException("Invalid Key Execption", e); } catch (IOException e) { throw new CryptoTokenOfflineException("IOException Execption", e); } catch (CertificateException e) { throw new CryptoTokenOfflineException("CertificateException Execption", e); } catch (NoSuchAlgorithmException e) { throw new CryptoTokenOfflineException("NoSuchAlgorithmException Execption", e); } catch (org.cesecore.keys.token.CryptoTokenOfflineException e) { throw new CryptoTokenOfflineException("CryptoTokenOfflineException Execption", e); } catch (NoSuchProviderException e) { throw new CryptoTokenOfflineException("NoSuchProviderException Execption", e); } catch (UnrecoverableKeyException e) { throw new CryptoTokenOfflineException("UnrecoverableKeyException Execption", e); } catch (KeyStoreException e) { throw new CryptoTokenOfflineException("KeyStoreException Execption", e); } } @Override public Certificate generateSignerKeyAndGetCertificate(final String keyAlgorithm, final String keySpec, final String alias, char[] authCode, final Map<String, Object> params, final IServices services) throws TokenOutOfSpaceException, CryptoTokenOfflineException, DuplicateAliasException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, UnsupportedCryptoTokenParameter { return generateSignerKeyAndGetCertificate(keyAlgorithm, keySpec, alias, authCode); } @Override public void importCertificateChain(final List<Certificate> certChain, final String alias, final char[] athenticationCode, final Map<String, Object> params, final IServices services) throws CryptoTokenOfflineException { try { final KeyStore keyStore = delegate.getActivatedKeyStore(); final Key key = keyStore.getKey(alias, athenticationCode); CryptoTokenHelper.ensureNewPublicKeyMatchesOld(keyStore, alias, certChain.get(0)); keyStore.setKeyEntry(alias, key, athenticationCode, certChain.toArray(new Certificate[0])); } catch (KeyStoreException ex) { LOG.error(ex, ex); throw new CryptoTokenOfflineException(ex); } catch (NoSuchAlgorithmException ex) { LOG.error(ex, ex); throw new CryptoTokenOfflineException(ex); } catch (UnrecoverableKeyException ex) { LOG.error(ex, ex); throw new CryptoTokenOfflineException(ex); } } @Override public TokenSearchResults searchTokenEntries(final int startIndex, final int max, final QueryCriteria qc, final boolean includeData, Map<String, Object> params, final IServices services) throws CryptoTokenOfflineException, QueryException { try { return CryptoTokenHelper.searchTokenEntries(getKeyStore(), startIndex, max, qc, includeData); } catch (KeyStoreException ex) { throw new CryptoTokenOfflineException(ex); } } @Override public ICryptoInstance acquireCryptoInstance(String alias, Map<String, Object> params, RequestContext context) throws CryptoTokenOfflineException, NoSuchAliasException, InvalidAlgorithmParameterException, UnsupportedCryptoTokenParameter, IllegalRequestException { final PrivateKey privateKey = getPrivateKey(alias); final List<Certificate> certificateChain = getCertificateChain(alias); return new DefaultCryptoInstance(alias, context, delegate.getActivatedKeyStore().getProvider(), privateKey, certificateChain); } @Override public void releaseCryptoInstance(ICryptoInstance instance, RequestContext context) { // NOP } @Override public ICertReqData genCertificateRequest(ISignerCertReqInfo info, boolean explicitEccParameters, String keyAlias, IServices services) throws CryptoTokenOfflineException { return genCertificateRequest(info, explicitEccParameters, keyAlias); } private static class KeyStorePKCS11CryptoToken extends org.cesecore.keys.token.PKCS11CryptoToken { public KeyStorePKCS11CryptoToken() throws InstantiationException { super(); } public KeyStore getActivatedKeyStore() throws CryptoTokenOfflineException { try { return getKeyStore(); } catch (org.cesecore.keys.token.CryptoTokenOfflineException ex) { throw new CryptoTokenOfflineException(ex); } } } // TODO : Sun : This is a temporary function for creating self sign certificate private Certificate createSelfSignCertificate(String alias, String algorithm, char[] pin) throws CertificateException, IOException, org.cesecore.keys.token.CryptoTokenOfflineException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, CryptoTokenOfflineException, UnrecoverableKeyException, KeyStoreException { // PrivateKey privkey = (PrivateKey) delegate.getActivatedKeyStore().getKey(alias, pin); return delegate.getActivatedKeyStore().getCertificate(alias); /* X509CertInfo info = new X509CertInfo(); Date from = new Date(); Date to = new Date(from.getTime() + 365 * 86400000l); CertificateValidity interval = new CertificateValidity(from, to); BigInteger sn = new BigInteger(64, new SecureRandom()); X500Name owner = new X500Name("CN="+alias); info.set(X509CertInfo.VALIDITY, interval); info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn)); info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner)); info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner)); info.set(X509CertInfo.KEY, new CertificateX509Key(delegate.getPublicKey(alias))); info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid); info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo)); // Sign the cert to identify the algorithm that's used. X509CertImpl cert = new X509CertImpl(info); cert.sign(privkey, algorithm); return cert; */ } private byte[] cryptDataBytes(Cipher cipher, byte[] dataBytes, boolean encription) throws BadPaddingException, IllegalBlockSizeException, IOException { int blockSize = cipher.getBlockSize(); int outputSize = cipher.getOutputSize(blockSize); if (blockSize == 0) { blockSize = outputSize - 11; } int readingBlockSize = 0; if (encription) { readingBlockSize = blockSize; } else { readingBlockSize = outputSize; } int inLen = dataBytes.length; int fullBlockCount = inLen / readingBlockSize; ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); int inOffset = 0; for (int i = 0; i < fullBlockCount; i++) { outputStream.write(cipher.doFinal(dataBytes, inOffset, readingBlockSize)); inOffset += readingBlockSize; } if (inOffset < inLen) { outputStream.write(cipher.doFinal(dataBytes, inOffset, inLen - inOffset)); } return outputStream.toByteArray(); } }