2013-11-26 3 views
2

Мне нужно создать запрос сертификата PKCS10 для пары ключей RSA, хранящейся на криптокарте, с доступом через интерфейс PKCS11. Дело в том, что я не могу использовать стандартные алгоритмы RSA в процессе создания PKCS10, и я не могу получить секретный ключ от криптокарда, поэтому криптографические операции должны выполняться на стороне криптокарда. Как я могу подготовить (возможно, вручную) запрос PKCS10 с использованием интерфейса PKCS11 для подписания?Создание запроса сертификата PKCS10 в PKCS11 inJAVA

@Edit Теперь у меня есть ошибка, как это:

Exception in thread "main" java.security.ProviderException: Initialization failed 
    at sun.security.pkcs11.P11Signature.initialize(P11Signature.java:310) 
    at sun.security.pkcs11.P11Signature.engineInitSign(P11Signature.java:391) 
    at java.security.Signature$Delegate.engineInitSign(Signature.java:1127) 
    at java.security.Signature.initSign(Signature.java:511) 
    at pkcs11.Main.stworzPkcs10(Main.java:65) 
    at pkcs11.Main.main(Main.java:53) 
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_GENERAL_ERROR 
    at sun.security.pkcs11.wrapper.PKCS11.C_SignInit(Native Method) 
    at sun.security.pkcs11.P11Signature.initialize(P11Signature.java:302) 
    ... 5 more 
Java Result: 1 

и код:

String zawartoscPlikuKonfiguracyjnego = new String(
      "name=PKCS11\n" + 
      "library=" + sciezkaDoBibliotekiPkcs11); 

    FileOutputStream plikKonfiguracyjny = new FileOutputStream("pkcs11.cfg"); 
    plikKonfiguracyjny.write(zawartoscPlikuKonfiguracyjnego.getBytes()); 
    plikKonfiguracyjny.close(); 

    File test = new File("pkcs11.cfg"); 
    dostawcaPkcs11 = new SunPKCS11("pkcs11.cfg"); 
    Security.addProvider(dostawcaPkcs11); 

    interfejsPkcs11 = KeyStore.getInstance("PKCS11",dostawcaPkcs11);   
    pin = new JPasswordField(); 
    JOptionPane.showConfirmDialog(null, pin, "Podaj pin do tokena", JOptionPane.OK_CANCEL_OPTION); 

    interfejsPkcs11.load(null, pin.getPassword()); 

    Key kluczPrywatny = null; 
    Key kluczPubliczny = null; 

    Enumeration<String> aliasy = interfejsPkcs11.aliases(); 
    while(aliasy.hasMoreElements()) { 
     String alias = aliasy.nextElement(); 
     if(interfejsPkcs11.isKeyEntry(alias)) { 
      kluczPrywatny = interfejsPkcs11.getKey(alias, pin.getPassword()); 
     } else { 
      kluczPubliczny = interfejsPkcs11.getCertificate(alias).getPublicKey(); 
     } 
    } 

    PKCS10 pkcs10 = new PKCS10((PublicKey) kluczPubliczny); 
    Signature sygnatura = Signature.getInstance("SHA1WithRSA", dostawcaPkcs11); 
    sygnatura.initSign((PrivateKey) kluczPrywatny); 
    X500Name nazwaX500 = new X500Name("Certyfikat testowy", "Developer", "Developer", "Warszawa", "Mazovia", "PL"); 
    pkcs10.encodeAndSign(nazwaX500, sygnatura); 

ответ

3

Я бы порекомендовал вам попробовать использовать ВС PKCS # 11 поставщика. Вам нужно будет следовать the documentation, чтобы понять, как настроить поставщика для использования DLL, предоставленного поставщиком криптокарда. (Также стоит расспросить их рекомендуемый подход к доступу к криптокарду с Java).

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

String CN = "Mr Foo"; 
String OU = "Foo Department"; 
String O = "Foo Ltd."; 
String L = "Foosville"; 
String S = "Foouisiana"; 
String C = "GB"; 

PublicKey publicKey = //... load public key from keystore 
PrivateKey privateKey = //... load private key from keystore 

PKCS10 pkcs10 = new PKCS10(publicKey); 
Signature signature = Signature.getInstance("SHA1WithRSA"); // or whatever 
signature.initSign(privateKey);  
X500Name x500Name = new X500Name(CN, OU, O, L, S, C); 
pkcs10.encodeAndSign(new X500Signer(signature, x500Name)); 

try (ByteArrayOutputStream bs = new ByteArrayOutputStream(); 
    PrintStream ps = new PrintStream(bs)) { 
    pkcs10.print(ps); 
    byte[] c = bs.toByteArray(); // <-- this is it! (save to disk maybe?) 
} 
+0

Спасибо за ваш ответ. Я вижу, что вы используете стандартный механизм обозначения RSA. Проблема в том, что я должен использовать метод C_Sign из PKCS # 11, потому что он модифицировал алгоритмы, немного отличающиеся от RSA, но поддающиеся проверке со стандартным открытым ключом RSA. Теперь у меня работает поставщик PKCS # 11 и загруженный открытый ключ из хранилища, но я не могу получить закрытый ключ, потому что он чувствительный. –

+0

@DarkTomel Пожалуйста, объясните, что вы подразумеваете под «модифицированными алгоритмами». Кроме того, пожалуйста, объясните, что вы подразумеваете под «не может получить закрытый ключ» - возникает ли ошибка при попытке получить объект «PrivateKey» из хранилища ключей? Если да, отправьте эту ошибку. –

+0

Я делаю редактирование в первом посте, потому что места недостаточно. –

Смежные вопросы