问题
I have a Java KeyStore with couple of entries sharing the same alias (duplicates). When I do a getEntry(...)
or getCertificate(...)
or getKey(...)
, I always get the first entry in all the cases. How do I always get the ones that I want?
I have tried exporting the first entry to an external file (using keytool
), and then deleting the first entry from the original KeyStore, and then importing back the exported entry with a different alias. This would work if the entry is a Trusted Certificate. But it wouldn't work if it is a PrivateKeyEntry or a SecretKeyEntry.
Is there any feasible solution/fix to handle this scenario?
回答1:
There is one way of fixing the duplicate aliases. Since there is no direct way of fixing this issue, we can fix the duplicate aliases manually. You can run this code below to fix the duplicate aliases occurrences, (it is a one time thing).
public static void removeDuplicateAliases() throws NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, KeyStoreException,
UnrecoverableEntryException
{
final String KEYSTORE_TYPE = "KEYSTORE_TYPE";
final String KEYSTORE_PATH = "KEYSTORE_PATH";
final char[] KEYSTORE_PASSWORD = "KEYSTORE_PASSWORD".toCharArray();
KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE);
ks.load(new FileInputStream(new File(KEYSTORE_PATH)), KEYSTORE_PASSWORD);
Enumeration<String> aliases = ks.aliases();
Map<String, List<KeyStore.Entry>> keyStoreEntriesMap = new LinkedHashMap<String, List<KeyStore.Entry>>();
while (aliases.hasMoreElements())
{
String alias = aliases.nextElement();
KeyStore.Entry entry = null;
try
{
entry = ks.getEntry(alias, new KeyStore.PasswordProtection(KEYSTORE_PASSWORD));
}
catch (UnsupportedOperationException e)
{
entry = ks.getEntry(alias, null);
}
if (!keyStoreEntriesMap.containsKey(alias))
{
List<KeyStore.Entry> aliasEntry = new ArrayList<KeyStore.Entry>();
aliasEntry.add(entry);
keyStoreEntriesMap.put(alias, aliasEntry);
}
else
{
keyStoreEntriesMap.get(alias).add(entry);
}
}
for (Map.Entry<String, List<KeyStore.Entry>> entry : keyStoreEntriesMap.entrySet())
{
if (entry.getValue().size() > 1)
{
System.out.println("Multiple entries found under same alias - \'" + entry.getKey() + "\'");
int counter = 1;
for (KeyStore.Entry each : entry.getValue())
{
ks.deleteEntry(entry.getKey());
String newAlias = entry.getKey() + "-" + counter;
if (each instanceof TrustedCertificateEntry)
ks.setEntry(newAlias, each, null);
else
ks.setEntry(newAlias, each, new KeyStore.PasswordProtection(PASSWORD));
System.out.println("\t(" + counter + " of " + entry.getValue().size() + ") Entry moved to new alias \'" + newAlias + "\'");
counter++;
}
System.out.println();
}
}
ks.store(new FileOutputStream(new File(KEYSTORE_PATH)), PASSWORD);
System.out.println("Done!!");
}
What this basically does is group all the entries that have common aliases, and moves/creates a new entry with a new alias (incremental counter appended to the existing alias) and deletes all the original entries.
You can see the new aliases in your console.
P.S: It is advised to have your original KeyStore backed-up.
回答2:
Instead of using KeyStore.deleteEntry (which causes problems for private keys), use KeyStore.setCertificateEntry(Alias, Certificate).
来源:https://stackoverflow.com/questions/36292718/java-keystore-duplicate-aliases