Что означает цепочка Certificate[] в Keystore.setKeyEntry() и как получить эту информацию из JKS или PKCS12?

Я знаю, что такое цепочка сертификатов. В java при работе с объектами KeyStore мы можем добавлять сертификаты и закрытые ключи в объект хранилища ключей.

для этого делаем:

        KeyStore sourceKeystore = KeyStore.getInstance("jks");
        try (InputStream stream = new BufferedInputStream(Files.newInputStream(sourceKeystorePath))) {
            sourceKeystore.load(stream, sourceKeystorePassword);
        }

        KeyStore destKeystore = KeyStore.getInstance("jks");
        destKeystore.load(null, destKeystorePassword);

        Enumeration<String> aliasList = sourceKeystore.aliases();
        while (aliasList.hasMoreElements()) {
            String alias = aliasList.nextElement();
            destKeystore.setCertificateEntry(alias, sourceKeystore.getCertificate(alias));
            if(sourceKeystore.isKeyEntry(alias)) {
                System.out.println(alias + " : is private key");
                Key key = sourceKeystore.getKey(alias, "secret".toCharArray());
                Certificate[] chain = new Certificate[1];
                chain[0] = sourceKeystore.getCertificate(alias);
                destKeystore.setKeyEntry(alias, key, "secret".toCharArray(), chain);
            }
        }

        try (OutputStream stream = new BufferedOutputStream(Files.newOutputStream(destKeystorePath))) {
            destKeystore.store(stream, destKeystorePassword);
        }

Что я хочу понять, так это destKeystore.setKeyEntry(). Когда я даю цепочку сертификатов в качестве параметра, могу ли я указать такой массив сертификатов?

  1. [рутцерт, интерсерт, основной сертификат]
  2. [основной сертификат, интерсерт, корневой сертификат]
  3. [основной сертификат]

Первый вопрос: что означают эти различные способы установки цепочки?

Второй вопрос: Также если у меня есть файл JKS. Как найти это точное значение цепочки сертификатов и в каком порядке цепочка сертификатов была установлена ​​для закрытого ключа в этом хранилище ключей? в основном я имею в виду, что я хочу узнать, какой параметр Certificate[] был передан в KeyStore.setKeyEntry() в этом файле JKS


person vkp    schedule 10.06.2019    source источник


Ответы (1)


Во-первых, основы того, как формируется цепочка сертификатов.

Когда вы изначально создаете key pair любыми средствами (keytool, openssl и т. д.), он в основном состоит из private key, связанного с его self-signed certificate, где самозаверяющий сертификат содержит public key. Затем из пары ключей создается PKCS#10 (запрос на подпись сертификата). в основном некоторая идентификационная информация о владельце закрытого ключа + открытый ключ, собранная вместе и подписанная закрытым ключом. Этот CSR будет отправлен Certificate Authority для получения подписанного сертификата. ЦС подписывает его и отвечает цепочкой сертификатов. Эта полученная цепочка сертификатов затем обновляется до первоначально созданного закрытого ключа, заменяя старый самозаверяющий сертификат. Теперь мы называем эту пару ключей подписанной парой ключей, она больше не является самоподписанной.

Теперь понятно, что отправил ЦС. В основном цепочка сертификатов, отправляемая ЦС, выглядит так:

CA Certificate (self-signed)
|
|__ 2. Sub CA Certificate (signed by the above CA)
        |
        |__ 1. Sub-sub CA Certificate (if any) (signed by the above Sub CA)
                |
                |__ 0. End Entity Certificate (your certificate, signed by the above cert)

Если вы посмотрите на индексы сертификатов, они говорят следующее:

  • Самый важный сертификат — это первый сертификат (также известный как сертификат пользователя/узла).
  • Наименее важный сертификат — это последний сертификат (также известный как сертификат ЦС).

В терминологии кодирования первый (нулевой) элемент массива сертификатов — это сертификат пользователя, а последний элемент массива сертификатов — сертификат ЦС. Это означает, что соответствующий открытый ключ, принадлежащий вашему закрытому ключу, можно найти в первом сертификате.

В 99% случаев вам не придется самостоятельно заниматься порядком цепочки сертификатов. Когда CA отвечает цепочкой сертификатов, она обычно находится в правильном порядке. Все, что вам нужно сделать, это обновить цепочку сертификатов до вашего закрытого ключа.

Теперь ответы на ваши вопросы:

  1. Поскольку вы находитесь в мире java, первый порядок сертификатов считается обратным (неправильным). Второй вариант правильный. Третий вариант тоже правильный, но желательно всегда включать всю цепочку сертификатов, если она у вас есть.
  2. В вашем коде, где вы делаете:
Certificate[] chain = new Certificate[1];
chain[0] = sourceKeystore.getCertificate(alias);
destKeystore.setKeyEntry(alias, key, "secret".toCharArray(), chain);

также доступен метод возврата всей цепочки сертификатов, связанной с закрытым ключом getCertificateChain(). Где вы можете просто сделать:

Certificate[] chain = sourceKeystore.getCertificateChain(alias);
destKeystore.setKeyEntry(alias, key, "secret".toCharArray(), chain);

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

person always_a_rookie    schedule 10.06.2019
comment
@always_a_rookie_to_learn.Спасибо за развернутый ответ. Только одно, нет ли разницы между вариантом 2 и 3? Каковы будут возможные последствия этого действия. PS: можете дать ссылки на ресурсы, где я могу во всем этом разобраться досконально, если они у вас есть? - person vkp; 10.06.2019
comment
Не принято просто добавлять одноранговый сертификат из цепочки, если у вас есть вся цепочка сертификатов, я настоятельно рекомендую добавить ее целиком. Документация Java — ваш лучший друг для этого. - person always_a_rookie; 11.06.2019
comment
@always_a_rookie_to_learn : Возможно ли иметь закрытый ключ без пароля? В приведенном выше случае secret.toCharArray(). Если возможно, как мы получим закрытый ключ в этом случае. - person Rakesh R Nair; 16.10.2019