Java - PKCS11 и MSKeyStore - PullRequest
       35

Java - PKCS11 и MSKeyStore

2 голосов
/ 10 ноября 2011

Я пытаюсь подписать строку с другими сертификатами из MS-KeyStore.Но я знаю, что в MS-Keystore есть импортированные ключи от токена.Итак, моя проблема в том, что - если я прохожу через хранилище ключей и пытаюсь подписать сертификат с ссылкой на pkcs11, я получаю всплывающее окно для ввода пароля pkcs11.Как я могу проверить, является ли сертификат моим токеном?

Заранее спасибо !!!

На данный момент это мой код:

  String alias;
    byte[] data = "test".getBytes();
    char[] pin = "pass".toCharArray();

    try {


        KeyStore ks = KeyStore.getInstance("Windows-MY");
        ks.load(null, pin);
        System.out.println("Provider: "+ks.getProvider());
        System.out.println("KS size: " + ks.size());

        Enumeration enumeration = ks.aliases();

        while (enumeration.hasMoreElements()) {
            alias = (String) enumeration.nextElement();

            PrivateKey privateKey = (PrivateKey) ks.getKey(alias, null);
            Certificate certificate = ks.getCertificate(alias);

            Provider provider = ks.getProvider();
            Signature signature = Signature.getInstance("SHA1withRSA", provider);
            try {
                signature.initSign(privateKey);
                signature.update(data);

                byte[] signedSignature = signature.sign();
                System.out.println("\tGenerated signature for " + alias);

                signature.initVerify(certificate);
                signature.update(data);
                if (signature.verify(signedSignature)) {
                    System.out.println("\tSignature verifified for " + alias);
                } else {
                    System.out.println("\tCould not verify signature for " + alias);
                }
            } catch (Exception ex) {
                System.out.println("\tError for " + alias);
            }

        }

    } catch (KeyStoreException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (CertificateException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (FileNotFoundException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (IOException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    }

Ответы [ 2 ]

0 голосов
/ 30 ноября 2011

В хранилищах ключей Java псевдоним ключа и сертификата должен быть связан.По сути, запись закрытого ключа - это цепочка закрытых ключей + сертификатов.Таким образом, сертификат всегда должен приходить из хранилища ключей.Если сертификат пришел от фактического токена, конечно, до реализации хранилища ключей.Единственный способ проверить, были ли они на самом деле с токена, - это извлечь их, используя другой метод (например, считывание байтов сертификата непосредственно с токена).Ссылка на запоминающее устройство для сертификатов отсутствует, если это то, что вам нужно.

Конечно, имеет смысл проверить всю цепочку сертификатов вплоть до корневого сертификата.Если корневой сертификат меняется не часто, вы можете рассмотреть вопрос о сохранении сертификата или хеша над корневым сертификатом в ресурсе, поставляемом вместе с вашим приложением, или распространении его в стандартном хранилище ключей Java.

0 голосов
/ 13 ноября 2011

Боюсь, вы не можете достоверно указать источник сертификата, по крайней мере, не на уровне Java для поставщика MS CAPI. Но это часть проекта - MS CAPI более или менее собирается инкапсулировать и скрывать происхождение сертификатов / ключей.

Безопасный способ сообщить, что ваш ключ / сертификат исходит от устройства PKCS # 11, - это использовать поставщика SUN PKCS # 11 . Это, однако, имеет недостаток, заключающийся в том, что вам нужно будет указывать путь к вашей собственной библиотеке PKCS # 11 либо статически (в файле java.security, где вы можете статически конфигурировать провайдеров), либо динамически запрашивать его как ввод данных пользователем.

Если использование провайдера PKCS # 11 является слишком большой проблемой в вашей ситуации, я бы предложил реализовать диалог выбора сертификата, который фильтрует подходящие сертификаты. Нет немедленного усиления безопасности, ограничивая MSCAPI сертификатами, исходящими от PKCS # 11 - возможно, есть веская причина, по которой у вашего пользователя установлены другие сертификаты / ключи (часто в форме файлов PKCS # 12). Вам следует только проверить (и чтобы помочь пользователю уже отфильтровать сертификаты, повторяющие этот критерий), чтобы окончательно выбранный сертификат / ключ соответствовал вашим критериям: правильное использование ключа (например, цифровая подпись), надежное использование расширенного ключа, приемлемые или известные политики, присутствующие в сертификаты и т. д.

В ЕС мы постепенно развиваемся к понятию «Квалифицированные сертификаты на защищенном устройстве для создания подписи». Это подразумевает, что сертификаты, поставляемые на такое устройство (например, смарт-карты), будут содержать специальную политику, и центрам сертификации запрещено использовать эти политики для любых других сертификатов, например сертификатов программного обеспечения. Таким образом, это эффективно позволит вам убедиться, что сертификат исходит от безопасного аппаратного устройства. Вы можете проверить, поддерживают ли соответствующие сертификаты эту функцию. В этом документе ETSI перечислены соответствующие OID, которые вы должны искать.

...