Какво означава веригата Certificate[] в Keystore.setKeyEntry() и как да получите тази информация от JKS или PKCS12?

Знам какво е верига от сертификати. В Java, когато работим с KeyStore обекти, можем да добавяме сертификати и частни ключове към обект на 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. [rootCert, interCert, mainCert]
  2. [mainCert, interCert, rootCert]
  3. [mainCert]

Първи въпрос: какво означават тези различни начини за настройка на веригата?

Втори въпрос: Също така, ако имам JKS файл. Как да намеря тази точна стойност на веригата от сертификати и в какъв ред е зададена веригата от сертификати за частен ключ в това KeyStore? основно това, което имам предвид е, че искам да разбера какъв беше параметърът 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 го подписва и отговаря с верига от сертификати. Тази получена верига от сертификати след това се актуализира до първоначално създадения частен ключ, заменяйки стария самоподписан сертификат. Сега наричаме тази двойка ключове подписана двойка ключове, тя вече не е самоподписана.

Сега разбирам какво е изпратил CA. По принцип веригата от сертификати, изпратени от CA, изглежда така:

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)

Ако погледнете индексите на сертификатите, те казват следното:

  • Най-важният сертификат е първият сертификат (известен още като потребителски/партньорски сертификат)
  • Най-маловажният сертификат е последният сертификат (известен още като CA сертификат)

В терминологията на кодирането първият (нулев) елемент от масива от сертификати е потребителският сертификат, а последният елемент от масива от сертификати е CA сертификатът. Което означава, че съответстващият публичен ключ, който принадлежи на вашия частен ключ, може да бъде намерен в първия сертификат.

В 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