summaryrefslogtreecommitdiff
path: root/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/KeyStoreUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/KeyStoreUtils.java')
-rw-r--r--src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/KeyStoreUtils.java686
1 files changed, 686 insertions, 0 deletions
diff --git a/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/KeyStoreUtils.java b/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/KeyStoreUtils.java
new file mode 100644
index 0000000..46f6fc5
--- /dev/null
+++ b/src/plugins/certmanager/src/com/motorolamobility/studio/android/certmanager/core/KeyStoreUtils.java
@@ -0,0 +1,686 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorolamobility.studio.android.certmanager.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.KeyStore.Builder;
+import java.security.KeyStore.Entry;
+import java.security.KeyStore.PasswordProtection;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.KeyStore.ProtectionParameter;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Map;
+
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.X500NameBuilder;
+import org.bouncycastle.asn1.x500.style.BCStrictStyle;
+import org.bouncycastle.asn1.x500.style.BCStyle;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
+import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.bc.BcContentSignerBuilder;
+import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
+import org.eclipse.osgi.util.NLS;
+
+import com.motorola.studio.android.common.log.StudioLogger;
+import com.motorola.studio.android.common.utilities.FileUtil;
+import com.motorolamobility.studio.android.certmanager.exception.InvalidPasswordException;
+import com.motorolamobility.studio.android.certmanager.exception.KeyStoreManagerException;
+import com.motorolamobility.studio.android.certmanager.i18n.CertificateManagerNLS;
+import com.motorolamobility.studio.android.certmanager.ui.model.CertificateDetailsInfo;
+
+public class KeyStoreUtils
+{
+ private static final String ERROR_DELETING_ALIAS =
+ CertificateManagerNLS.KeyStoreUtils_ErrorDeletingAlias;
+
+ /**
+ * Creates a new empty KeyStore, from the default type, located at keyStoreFile with the password, password
+ * @param keyStoreFile The file pointing o where the new KeyStore will be located
+ * @param password the password for the new KeyStore
+ * @return the {@link KeyStore} representing the new KeyStore
+ * @throws InvalidPasswordException
+ * @throws KeyStoreException if KeyStore can't be created
+ */
+ public static KeyStore createKeystore(File keyStoreFile, char[] password)
+ throws KeyStoreManagerException, InvalidPasswordException
+ {
+ return createKeystore(keyStoreFile, KeyStore.getDefaultType(), password);
+ }
+
+ /**
+ * Creates a new empty KeyStore, located at keyStoreFile with the password, password
+ * @param keyStoreFile The file pointing o where the new KeyStore will be located
+ * @param keyStoreType The type of the new KeyStore
+ * @param password the password for the new KeyStore
+ * @return the {@link KeyStore} representing the new KeyStore
+ * @throws InvalidPasswordException
+ * @throws KeyStoreException if KeyStore can't be created
+ */
+ public static KeyStore createKeystore(File keyStoreFile, String keyStoreType, char[] password)
+ throws KeyStoreManagerException, InvalidPasswordException
+ {
+ KeyStore keyStore = null;
+ if ((keyStoreFile != null) && !keyStoreFile.exists())
+ {
+ keyStore = loadKeystore(keyStoreFile, password, keyStoreType);
+ try
+ {
+ writeKeyStore(keyStore, password, keyStoreFile);
+ }
+ catch (Exception e)
+ {
+ throw new KeyStoreManagerException(NLS.bind(
+ CertificateManagerNLS.KeyStoreUtils_Error_WriteKeyStore, keyStoreFile), e);
+ }
+ }
+ else
+ {
+ throw new KeyStoreManagerException(NLS.bind(
+ CertificateManagerNLS.KeyStoreUtils_Error_FileAlreadyExists, keyStoreFile));
+ }
+
+ return keyStore;
+ }
+
+ public static void writeKeyStore(KeyStore keyStore, char[] password, File keyStoreFile)
+ throws FileNotFoundException, KeyStoreException, IOException, NoSuchAlgorithmException,
+ CertificateException, KeyStoreManagerException, InvalidPasswordException
+ {
+
+ writeKeyStore(keyStore, null, password, keyStoreFile);
+ }
+
+ private static void writeKeyStore(KeyStore keyStore, char[] oldPassword, char[] newPassword,
+ File keyStoreFile) throws FileNotFoundException, KeyStoreException, IOException,
+ NoSuchAlgorithmException, CertificateException, KeyStoreManagerException,
+ InvalidPasswordException
+ {
+ FileOutputStream fos = null;
+ try
+ {
+ if (oldPassword != null)
+ {
+ if (loadKeystore(keyStoreFile, oldPassword, keyStore.getType()) != null)
+ {
+ fos = new FileOutputStream(keyStoreFile);
+ keyStore.store(fos, newPassword);
+ }
+ }
+ else
+ {
+ fos = new FileOutputStream(keyStoreFile);
+ keyStore.store(fos, newPassword);
+ }
+ }
+ finally
+ {
+ if (fos != null)
+ {
+ try
+ {
+ fos.close();
+ }
+ catch (IOException e)
+ {
+ StudioLogger.error("Could not close steam while writing keystore file. "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+
+ /**
+ * Loads a KeyStore from a given file from the default type, usually JKS.
+ * If keyStoreFile path don't exist then a new empty KeyStore will be created on the given location.
+ * <b>Note:</b> Calling this method is the same as calling loadKeystore(keyStoreFile, password, KeyStore.getDefaultType())
+ * @param keyStoreFile The keyStore location.
+ * @param password The KeyStore password
+ * @return the {@link KeyStore} representing the file.
+ * @throws KeyStoreManagerException
+ * @throws InvalidPasswordException
+ */
+ public static KeyStore loadKeystore(File keyStoreFile, char[] password)
+ throws KeyStoreManagerException, InvalidPasswordException
+ {
+ return loadKeystore(keyStoreFile, password, KeyStore.getDefaultType());
+ }
+
+ /**
+ * Loads a KeyStore from a given file.
+ * If keyStoreFile path don't exist then a new empty KeyStore will be created on memory.
+ * If you want o create a new KeyStore file, calling createStore is recommended.
+ * @param keyStoreFile The keyStore location.
+ * @param password The KeyStore password
+ * @param storeType The Type of the keystore o be loaded.
+ * @return the {@link KeyStore} representing the file.
+ * @throws KeyStoreManagerException
+ * @throws InvalidPasswordException
+ */
+ public static KeyStore loadKeystore(File keyStoreFile, char[] password, String storeType)
+ throws KeyStoreManagerException, InvalidPasswordException
+ {
+ KeyStore keyStore = null;
+ FileInputStream fis = null;
+ try
+ {
+ keyStore = KeyStore.getInstance(storeType);
+
+ if ((keyStoreFile != null) && keyStoreFile.exists() && (keyStoreFile.length() > 0))
+ {
+ fis = new FileInputStream(keyStoreFile);
+ }
+
+ //fis = null means a new keyStore will be created
+ keyStore.load(fis, password);
+ }
+ catch (IOException e)
+ {
+ if (e.getMessage().contains("password was incorrect")
+ || (e.getCause() instanceof UnrecoverableKeyException))
+ {
+ throw new InvalidPasswordException(e.getMessage());
+ }
+ else
+ {
+ throw new KeyStoreManagerException(NLS.bind(
+ CertificateManagerNLS.KeyStoreUtils_Error_LoadKeyStore, keyStoreFile), e);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new KeyStoreManagerException(NLS.bind(
+ CertificateManagerNLS.KeyStoreUtils_Error_LoadKeyStore, keyStoreFile), e);
+ }
+ finally
+ {
+ if (fis != null)
+ {
+ try
+ {
+ fis.close();
+ }
+ catch (IOException e)
+ {
+ StudioLogger.error("Could not close steam while loading keystore. "
+ + e.getMessage());
+ }
+ }
+ }
+
+ return keyStore;
+ }
+
+ /**
+ * Simply deletes the KeyStore File
+ * @param keyStoreFile teh KeyStore file to be deleted.
+ * @throws KeyStoreException If any error occur.
+ */
+ public static void deleteKeystore(File keyStoreFile) throws KeyStoreManagerException
+ {
+ try
+ {
+ FileUtil.deleteFile(keyStoreFile);
+ }
+ catch (IOException e)
+ {
+ throw new KeyStoreManagerException(NLS.bind(
+ CertificateManagerNLS.KeyStoreUtils_Error_DeleteKeyStore, keyStoreFile), e);
+ }
+ }
+
+ /**
+ * Write the keyStore in to the given file, protecting it with password.
+ * Warn: Since there's actually no way to change the password this method will overwrite the existing file with the keyStore contents,
+ * without further warning.
+ * @param keyStore the {@link KeyStore} to be written.
+ * @param keyStoreFile The KeyStore location
+ * @param oldPassword
+ * @param sourcePassword the new Password
+ * @throws KeyStoreException If file could no be write.
+ */
+ public static void changeKeystorePasswd(KeyStore keyStore, File keyStoreFile,
+ char[] oldPassword, char[] newPassword) throws KeyStoreManagerException
+ {
+ try
+ {
+ keyStore = loadKeystore(keyStoreFile, oldPassword, keyStore.getType());
+ writeKeyStore(keyStore, oldPassword, newPassword, keyStoreFile);
+ }
+ catch (Exception e)
+ {
+ throw new KeyStoreManagerException(NLS.bind(
+ CertificateManagerNLS.KeyStoreUtils_Error_WriteKeyStore, keyStoreFile), e);
+ }
+ }
+
+ /**
+ * Adds a new enty to a given keyStore.
+ * @param keyStore The Keystore that will receive the entry
+ * @param keyStorePassword The KeyStore password
+ * @param keyStoreFile The KeyStore file path
+ * @param alias The new entry alias
+ * @param entry The Entry to be added
+ * @param entryPassword The password to protect the entry
+ * @throws KeyStoreManagerException if any error occurs.
+ */
+ public static void addEntry(KeyStore keyStore, char[] keyStorePassword, File keyStoreFile,
+ String alias, Entry entry, char[] entryPassword) throws KeyStoreManagerException
+ {
+ try
+ {
+ PasswordProtection passwordProtection = new KeyStore.PasswordProtection(entryPassword);
+ keyStore = loadKeystore(keyStoreFile, keyStorePassword, keyStore.getType());
+
+ if (!keyStore.containsAlias(alias))
+ {
+ keyStore.setEntry(alias, entry, passwordProtection);
+ writeKeyStore(keyStore, keyStorePassword, keyStoreFile);
+ }
+ else
+ {
+ throw new KeyStoreManagerException(NLS.bind("Alias \"{0}\" already exists.", alias));
+ }
+
+ }
+ catch (KeyStoreManagerException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new KeyStoreManagerException(NLS.bind(
+ CertificateManagerNLS.KeyStoreUtils_Error_AddEntryToKeyStore, alias), e);
+ }
+ }
+
+ /**
+ * Adds a new enty to a given keyStore.
+ * @param keyStore The Keystore that will receive the entry
+ * @param keyStorePassword The KeyStore password
+ * @param keyStoreFile The KeyStore file path
+ * @param alias The new entry alias
+ * @param entry The Entry to be added
+ * @param entryPassword The password to protect the entry
+ * @throws KeyStoreManagerException if any error occurs.
+ */
+ public static void changeEntryPassword(KeyStore keyStore, char[] keyStorePassword,
+ File keyStoreFile, String alias, Entry entry, char[] entryPassword)
+ throws KeyStoreManagerException
+ {
+ try
+ {
+ PasswordProtection passwordProtection = new KeyStore.PasswordProtection(entryPassword);
+ keyStore.setEntry(alias, entry, passwordProtection);
+ writeKeyStore(keyStore, keyStorePassword, keyStoreFile);
+ }
+ catch (Exception e)
+ {
+ throw new KeyStoreManagerException(NLS.bind(
+ "Error attempting to change password for {0}", alias), e);
+ }
+ }
+
+ /**
+ * Create a new X509 certificate for a given KeyPair
+ * @param keyPair the {@link KeyPair} used to create the certificate,
+ * RSAPublicKey and RSAPrivateKey are mandatory on keyPair, IllegalArgumentExeption will be thrown otherwise.
+ * @param issuerName The issuer name to be used on the certificate
+ * @param ownerName The owner name to be used on the certificate
+ * @param expireDate The expire date
+ * @return The {@link X509Certificate}
+ * @throws IOException
+ * @throws OperatorCreationException
+ * @throws CertificateException
+ */
+ public static X509Certificate createX509Certificate(KeyPair keyPair,
+ CertificateDetailsInfo certDetails) throws IOException, OperatorCreationException,
+ CertificateException
+ {
+
+ PublicKey publicKey = keyPair.getPublic();
+ PrivateKey privateKey = keyPair.getPrivate();
+ if (!(publicKey instanceof RSAPublicKey) || !(privateKey instanceof RSAPrivateKey))
+ {
+ throw new IllegalArgumentException(
+ CertificateManagerNLS.KeyStoreUtils_RSA_Keys_Expected);
+ }
+
+ RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
+ RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
+
+ //Transform the PublicKey into the BouncyCastle expected format
+ ASN1InputStream asn1InputStream = null;
+ X509Certificate x509Certificate = null;
+
+ try
+ {
+ asn1InputStream =
+ new ASN1InputStream(new ByteArrayInputStream(rsaPublicKey.getEncoded()));
+ SubjectPublicKeyInfo pubKey =
+ new SubjectPublicKeyInfo((ASN1Sequence) asn1InputStream.readObject());
+
+ X500NameBuilder nameBuilder = new X500NameBuilder(new BCStrictStyle());
+ addField(BCStyle.C, certDetails.getCountry(), nameBuilder);
+ addField(BCStyle.ST, certDetails.getState(), nameBuilder);
+ addField(BCStyle.L, certDetails.getLocality(), nameBuilder);
+ addField(BCStyle.O, certDetails.getOrganization(), nameBuilder);
+ addField(BCStyle.OU, certDetails.getOrganizationUnit(), nameBuilder);
+ addField(BCStyle.CN, certDetails.getCommonName(), nameBuilder);
+
+ X500Name subjectName = nameBuilder.build();
+ X500Name issuerName = subjectName;
+ X509v3CertificateBuilder certBuilder =
+ new X509v3CertificateBuilder(issuerName, BigInteger.valueOf(new SecureRandom()
+ .nextInt()), GregorianCalendar.getInstance().getTime(),
+ certDetails.getExpirationDate(), subjectName, pubKey);
+
+ AlgorithmIdentifier sigAlgId =
+ new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA"); //$NON-NLS-1$
+ AlgorithmIdentifier digAlgId =
+ new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
+ BcContentSignerBuilder sigGen = new BcRSAContentSignerBuilder(sigAlgId, digAlgId);
+
+ //Create RSAKeyParameters, the private key format expected by Bouncy Castle
+ RSAKeyParameters keyParams =
+ new RSAKeyParameters(true, rsaPrivateKey.getPrivateExponent(),
+ rsaPrivateKey.getModulus());
+
+ ContentSigner contentSigner = sigGen.build(keyParams);
+ X509CertificateHolder certificateHolder = certBuilder.build(contentSigner);
+
+ //Convert the X509Certificate from BouncyCastle format to the java.security format
+ JcaX509CertificateConverter certConverter = new JcaX509CertificateConverter();
+ x509Certificate = certConverter.getCertificate(certificateHolder);
+ }
+ finally
+ {
+ if (asn1InputStream != null)
+ {
+ try
+ {
+ asn1InputStream.close();
+ }
+ catch (IOException e)
+ {
+ StudioLogger.error("Could not close stream while creating X509 certificate. "
+ + e.getMessage());
+ }
+ }
+ }
+
+ return x509Certificate;
+ }
+
+ private static void addField(ASN1ObjectIdentifier objectId, String value,
+ X500NameBuilder nameBuilder)
+ {
+ if (value.length() > 0)
+ {
+ nameBuilder.addRDN(objectId, value);
+ }
+ }
+
+ /**
+ * Creates a new RSA KeyPair
+ * @return the new {@link KeyPair}
+ */
+ public static KeyPair genKeyPair() throws NoSuchAlgorithmException
+ {
+ KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); //$NON-NLS-1$
+ keyPairGen.initialize(2048); //As recommended by Android guys, key is created with 2048 bits.
+ KeyPair keyPair = keyPairGen.genKeyPair();
+ return keyPair;
+ }
+
+ /**
+ * Create a new private key entry inside the key pair
+ * @param keyPair
+ * @param x509Certificate
+ * @return
+ */
+ public static PrivateKeyEntry createPrivateKeyEntry(KeyPair keyPair,
+ X509Certificate x509Certificate)
+ {
+ Certificate[] certChain = new Certificate[]
+ {
+ x509Certificate
+ };
+ PrivateKeyEntry privateKeyEntry =
+ new KeyStore.PrivateKeyEntry(keyPair.getPrivate(), certChain);
+ return privateKeyEntry;
+ }
+
+ public static void deleteEntry(KeyStore keyStore, char[] password, File keyStoreFile,
+ String alias) throws KeyStoreManagerException
+ {
+ try
+ {
+ keyStore = loadKeystore(keyStoreFile, password, keyStore.getType());
+
+ keyStore.deleteEntry(alias);
+ writeKeyStore(keyStore, password, keyStoreFile);
+ }
+ catch (Exception e)
+ {
+ StudioLogger.error(KeyStoreUtils.class, ERROR_DELETING_ALIAS + alias, e);
+ throw new KeyStoreManagerException(ERROR_DELETING_ALIAS + alias, e);
+ }
+ }
+
+ /**
+ * Change a keyStore type.
+ * @param keyStoreFile The KeyStoreFile
+ * @param password The KeyStore Password
+ * @param originalType the original Type
+ * @param destinationType the new KeyStore Type
+ * @throws KeyStoreManagerException If any error occurs, the operation will be canceled and reverted automatically.
+ * @throws InvalidPasswordException
+ */
+ public static void changeKeyStoreType(File keyStoreFile, char[] password, String originalType,
+ String destinationType, Map<String, String> aliases) throws KeyStoreManagerException,
+ InvalidPasswordException
+ {
+ boolean rollBack = false;
+ String timeStamp = Long.toString(Calendar.getInstance().getTimeInMillis());
+ File oldKsFile = new File(keyStoreFile.getAbsolutePath() + "_" + timeStamp);
+ oldKsFile.delete();
+ boolean renamed = false;
+ renamed = keyStoreFile.renameTo(oldKsFile);
+ if (renamed)
+ {
+ try
+ {
+ Builder oldKsBuilder =
+ KeyStore.Builder.newInstance(originalType, null, oldKsFile,
+ new PasswordProtection(password));
+ KeyStore oldKeyStore = oldKsBuilder.getKeyStore();
+
+ KeyStore newKeyStore = createKeystore(keyStoreFile, destinationType, password);
+ for (String alias : aliases.keySet())
+ {
+ ProtectionParameter protectionParameter =
+ new PasswordProtection(aliases.get(alias).toCharArray());
+ Entry entry = oldKeyStore.getEntry(alias, protectionParameter);
+ newKeyStore.setEntry(alias, entry, protectionParameter);
+ }
+ writeKeyStore(newKeyStore, password, keyStoreFile);
+ }
+ catch (InvalidPasswordException e)
+ {
+ rollBack = true;
+ StudioLogger
+ .error(KeyStoreUtils.class,
+ "Invalid password while trying to create a new keystore, changing a keyStore type.",
+ e);
+
+ }
+ catch (Exception e)
+ {
+ if (e.getMessage().contains("password was incorrect")
+ || e.getCause().getMessage().contains("password was incorrect"))
+ {
+ keyStoreFile.delete();
+ oldKsFile.renameTo(keyStoreFile);
+ throw new InvalidPasswordException(e.getMessage());
+ }
+ else
+ {
+ StudioLogger.error(KeyStoreUtils.class,
+ "Exception occurred while attempting to change a keyStore type.", e);
+ rollBack = true;
+ }
+ }
+
+ if (rollBack)
+ {
+ keyStoreFile.delete();
+ oldKsFile.renameTo(keyStoreFile);
+
+ throw new KeyStoreManagerException(NLS.bind(
+ "Could not convert the KeyStore {0} to type {1}", keyStoreFile,
+ destinationType));
+ }
+ }
+ else
+ {
+ throw new KeyStoreManagerException(
+ NLS.bind(
+ "Could not convert the KeyStore {0} to type {1}, could not backup the current keyStore file, maybe it's in use by another program.",
+ keyStoreFile, destinationType));
+ }
+ oldKsFile.delete();
+ }
+
+ /**
+ * Import a set of entries from sourcekeystore into the targetkeystore.
+ * If alias already exists on the target keystore then the alias is concatenated with the
+ * source keystore file name.
+ * @param targetKeyStore
+ * @param targetFile
+ * @param targetType
+ * @param targetPasswd
+ * @param sourceKeyStore
+ * @param sourceKeyStoreFile
+ * @param sourcePasswd
+ * @param aliases a map<String, String> containing alias as key and its password as value. this method assume that the password is correct
+ * @throws InvalidPasswordException
+ * @throws KeyStoreManagerException
+ */
+ public static void importKeys(KeyStore targetKeyStore, File targetFile, String targetType,
+ char[] targetPasswd, KeyStore sourceKeyStore, File sourceKeyStoreFile,
+ char[] sourcePasswd, Map<String, String> aliases) throws InvalidPasswordException,
+ KeyStoreManagerException
+ {
+ if (!isValidKeyStorePasswd(targetFile, targetType, targetPasswd))
+ {
+ throw new InvalidPasswordException(
+ CertificateManagerNLS.PasswordChanged_InvalidKeystorePassword);
+ }
+
+ try
+ {
+ for (String alias : aliases.keySet())
+ {
+ if (sourceKeyStore.containsAlias(alias))
+ {
+ ProtectionParameter protectionParameter =
+ new PasswordProtection(aliases.get(alias).toCharArray());
+ Entry entry = sourceKeyStore.getEntry(alias, protectionParameter);
+ if (targetKeyStore.containsAlias(alias))
+ {
+ alias += "_" + sourceKeyStoreFile.getName();
+ }
+ int i = 1;
+ while (targetKeyStore.containsAlias(alias))
+ {
+ alias += "_" + i;
+ i++;
+ }
+ targetKeyStore.setEntry(alias, entry, protectionParameter);
+ }
+ else
+ {
+ StudioLogger
+ .error(KeyStoreUtils.class,
+ NLS.bind(
+ "Alias {0} could not be imported because it doesn't exists on originKeyStore",
+ alias));
+ }
+ }
+ writeKeyStore(targetKeyStore, targetPasswd, targetFile);
+ }
+ catch (Exception e)
+ {
+ throw new KeyStoreManagerException("Could not import the selected aliases into "
+ + targetFile.getName(), e);
+ }
+ }
+
+ /**
+ * Verifies if the password if valid
+ * @param keyStoreFile
+ * @param keyStoreType
+ * @param passwd
+ * @return true if password is valid, false otherwise.
+ * @throws KeyStoreManagerException
+ */
+ public static boolean isValidKeyStorePasswd(File keyStoreFile, String keyStoreType,
+ char[] passwd) throws KeyStoreManagerException
+ {
+ KeyStore keystore = null;
+ try
+ {
+ keystore = loadKeystore(keyStoreFile, passwd, keyStoreType);
+ }
+ catch (InvalidPasswordException e)
+ {
+ //Do nothing, password is invalid
+ }
+ return keystore != null;
+ }
+}