2016-03-29 4 views
1

У меня есть Java KeyStore с парой записей, имеющих один и тот же псевдоним (дубликаты). Когда я делаю getEntry(...) или getCertificate(...) или getKey(...), я всегда получаю первую запись во всех случаях. Как я всегда получаю те, которые мне нужны?Java KeyStore дубликаты псевдонимов

Я попытался экспортировать первую запись во внешний файл (используя keytool), а затем удалив первую запись из исходного KeyStore и импортируя экспортированную запись с другим псевдонимом. Это будет работать, если запись является доверенным сертификатом. Но это не сработает, если это PrivateKeyEntry или SecretKeyEntry.

Есть ли возможное решение/исправление для обработки этого сценария?

ответ

1

Существует один способ установления дублирующих псевдонимов. Поскольку нет прямого способа устранить эту проблему, мы можем исправить дубликаты псевдонимов вручную. Вы можете запустить этот код ниже, чтобы исправить дубликаты алиасов (это одно время).

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!!"); 
} 

То, что это в основном делает это сгруппировать все записи, которые имеют общие псевдонимы, и движется/создает новую запись с новым псевдонимом (инкрементный счетчик добавляется к существующему псевдонима) и удаляет все исходные данные.

Вы можете увидеть новые псевдонимы в консоли.

P.S: Рекомендуется иметь оригинальный резервный копир KeyStore.

+0

Мультимап сделает этот код более читабельным. –

0

Вместо использования KeyStore.deleteEntry (что вызывает проблемы с закрытыми ключами), используйте KeyStore.setCertificateEntry (Alias, Certificate).