2013-03-19 21 views
7

następujący kod tworzy kontekst uwierzytelnionego klienta SSL przy użyciu urządzenia PKCS # 11 (karta inteligentna). To wszystko działa świetnie z Java 6:Uwierzytelnianie klienta SSL za pomocą karty inteligentnej działa w języku Java 6, ale kończy się niepowodzeniem w języku Java 7

// Configure the SunPkcs11 provider 
String pkcs11config; 
pkcs11config = "name = Cryptoki"; 
pkcs11config += "\nlibrary = /SCDriver/libbit4ipki.dylib"; 
InputStream confStream = new ByteArrayInputStream(pkcs11config.getBytes()); 
SunPKCS11 sunpkcs11 = new SunPKCS11(confStream); 
Security.addProvider(sunpkcs11); 

// Specify keystore builder parameters for PKCS#11 keystores 
Builder scBuilder = Builder.newInstance("PKCS11", sunpkcs11, new KeyStore.CallbackHandlerProtection(new PasswordRetriever())); 

// Create and init KeyManagerFactory 
KeyManagerFactory factory = KeyManagerFactory.getInstance("NewSunX509"); 
factory.init(new KeyStoreBuilderParameters(scBuilder)); 

// create and init ssl context 
m_ssl_context = SSLContext.getInstance("TLS"); 
m_ssl_context.init(factory.getKeyManagers(), new TrustManager[] {new PkTrustManager()}, null);  
SSLContext.setDefault(m_ssl_context); 

PkTrustManager jest prosty i klasa „pusty”, biorąc każdy certyfikat serwera/klienta na dobre, a PasswordRetriever po prostu prosi o hasło za pomocą okna dialogowego (Na życzenie mogę wysłać do nich kod źródłowy). Na Java 7 zamiast otrzymuję następujący wyjątek podczas uzgadniania SSL kontekstu SSL:

java.security.InvalidKeyException: Class does not represent an RSA key: sun.security.pkcs11.P11Key$P11PrivateKey 
    at iaik.pkcs.pkcs1.RSACipher.engineInit(Unknown Source) 
    at iaik.pkcs.pkcs1.RSACipher.engineInit(Unknown Source) 
    at iaik.security.rsa.RSA.init(Unknown Source) 
    at iaik.security.rsa.RawRSASignature.engineInitSign(Unknown Source) 
    at java.security.SignatureSpi.engineInitSign(SignatureSpi.java:103) 
    at java.security.Signature.initSign(Signature.java:529) 
    at sun.security.ssl.RSASignature.engineInitSign(RSASignature.java:125) 
    at java.security.Signature$Delegate.engineInitSign(Signature.java:1136) 
    at java.security.Signature.initSign(Signature.java:529) 
    at sun.security.ssl.HandshakeMessage$CertificateVerify.<init>(HandshakeMessage.java:1556) 
    at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:982) 
    ... 14 more 

W najlepszym wypadku, powiedziałbym coś zmieniło się w wewnętrzne Java, ale sprawdzenie dokumentacji Oracle, ja nie zrobił” t znaleźć żadnych rzekomych zmian w menedżerze kluczy NewSunX509 lub innych składnikach. Sprawdziłem dwukrotnie kod i wydaje się, że jest zgodny ze specyfikacją (bo na pewno coś mi brakowało!).

Próbowałem dodać flagi konfiguracyjne:

System.setProperty("javax.net.ssl.keyStoreType", "pkcs11"); 
System.setProperty("javax.net.ssl.keyStore", "NONE"); 
System.setProperty("javax.net.ssl.trustStoreType", "pkcs11"); 
System.setProperty("javax.net.ssl.trustStore", "NONE"); 
System.setProperty("javax.net.ssl.keyStoreProvider", sunpkcs11.getName()); 
JCEMapper.setProviderId(sunpkcs11.getName()); 

Ale żadna zmiana, ten sam błąd ... i nie są one wymagane w Javie 6, gdzie wszystko działa. Z góry dziękuję każdemu, kto może pomóc lub ma jakieś pomysły!

PS: Przez wniosek @owlstead dodany -Djava.security.debug = sunpkcs11 i uzyskałem następujący wynik:

SunPKCS11 loading ---DummyConfig-1--- 
sunpkcs11: Initializing PKCS#11 library /SCDriver/libbit4ipki.dylib 
Information for provider SunPKCS11-Cryptoki 
Library info: 
    cryptokiVersion: 2.20 
    manufacturerID: bit4id srl      
    flags: 0 
    libraryDescription: bit4id PKCS#11     
    libraryVersion: 1.02 
All slots: 0 
Slots with tokens: 0 
Slot info for slot 0: 
    slotDescription: bit4id miniLector-U38 00 00          
    manufacturerID: unknown       
    flags: CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT 
    hardwareVersion: 0.00 
    firmwareVersion: 0.00 
Token info for token in slot 0: 
    label: CNS        
    manufacturerID: ST Incard      
    model: CNS (LB)   
    serialNumber: 7420057800291590 
    flags: CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED 
    ulMaxSessionCount: CK_EFFECTIVELY_INFINITE 
    ulSessionCount: 0 
    ulMaxRwSessionCount: CK_EFFECTIVELY_INFINITE 
    ulRwSessionCount: CK_UNAVAILABLE_INFORMATION 
    ulMaxPinLen: 8 
    ulMinPinLen: 5 
    ulTotalPublicMemory: 31988 
    ulFreePublicMemory: CK_UNAVAILABLE_INFORMATION 
    ulTotalPrivateMemory: 780 
    ulFreePrivateMemory: CK_UNAVAILABLE_INFORMATION 
    hardwareVersion: 0.00 
    firmwareVersion: 0.00 
    utcTime: 0000000000000000 
Mechanism CKM_RSA_PKCS: 
    ulMinKeySize: 1024 
    ulMaxKeySize: 1024 
    flags: 2561 = CKF_HW | CKF_DECRYPT | CKF_SIGN 
Mechanism CKM_RSA_PKCS_KEY_PAIR_GEN: 
    ulMinKeySize: 1024 
    ulMaxKeySize: 1024 
    flags: 65537 = CKF_HW | CKF_GENERATE_KEY_PAIR 
Mechanism CKM_SHA1_RSA_PKCS: 
    ulMinKeySize: 1024 
    ulMaxKeySize: 1024 
    flags: 2049 = CKF_HW | CKF_SIGN 
Mechanism CKM_SHA_1: 
    ulMinKeySize: 0 
    ulMaxKeySize: 0 
    flags: 1024 = CKF_DIGEST 
Mechanism CKM_SHA256: 
    ulMinKeySize: 0 
    ulMaxKeySize: 0 
    flags: 1024 = CKF_DIGEST 
Mechanism CKM_SHA256_RSA_PKCS: 
    ulMinKeySize: 1024 
    ulMaxKeySize: 1024 
    flags: 2049 = CKF_HW | CKF_SIGN 
Mechanism CKM_SHA384: 
    ulMinKeySize: 0 
    ulMaxKeySize: 0 
    flags: 1024 = CKF_DIGEST 
Mechanism CKM_SHA384_RSA_PKCS: 
    ulMinKeySize: 1024 
    ulMaxKeySize: 1024 
    flags: 2049 = CKF_HW | CKF_SIGN 
Mechanism CKM_SHA512: 
    ulMinKeySize: 0 
    ulMaxKeySize: 0 
    flags: 1024 = CKF_DIGEST 
Mechanism CKM_SHA512_RSA_PKCS: 
    ulMinKeySize: 1024 
    ulMaxKeySize: 1024 
    flags: 2049 = CKF_HW | CKF_SIGN 
Mechanism CKM_RSA_X_509: 
    ulMinKeySize: 1024 
    ulMaxKeySize: 1024 
    flags: 2561 = CKF_HW | CKF_DECRYPT | CKF_SIGN 
Password per token PKCS11 [SunPKCS11-Cryptoki]: sunpkcs11: login succeeded 
sunpkcs11: user already logged in 
javax.net.ssl.SSLHandshakeException: Error signing certificate verify 
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) 
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1886) 
    *....... (continues with the exception as described above)* 

Uwaga: W ostatniej aktualizacji Java 6, mój kod przestaje działać na Java 6, jak również :(

+0

Czy możesz spróbować podać '-Djava.security.debug = sunpkcs11' do wiersza poleceń Java VM i opublikować wyjście? –

+0

Hi @ Ostestead, zrobiłem to, o co prosiłeś: w wiadomości jest żądane dane wyjściowe (certyfikat do podpisywania, którego próbuję użyć, to SHA256withRSA). – FrizzTheSnail

+0

Nie widzę niczego złego, może jest to jakaś pomyłka między klasą 'sun.security.pkcs11.P11Key $ P11PrivateKey' i otokowym opakowaniem IAIK PKCS # 11, które zostały użyte do implementacji dostawcy PKCS # 11. Ale to stanowiłoby błąd. Możesz zgłosić to jako takie i zobaczyć, co się stanie. –

Odpowiedz

7

rozwiązać dodając linię kodu:

Security.removeProvider("IAIK"); 

przed linią:

Security.addProvider(sunpkcs11); 

ta działa poprawnie ze wszystkimi wersjami java6 i java7 (mając nadzieję, że nie będzie ponownie wkręcić coś java8 ... :)

Wygląda dostawca IAIK wstawia się jako Dostawca PKCS11, ale następnie wykonuje połączenia z kluczem prywatnym, używając go jako klucza programowego ... ponieważ w rzeczywistości jest dostawcą oprogramowania.

+0

Tak, to jest powód. Patrząc uważnie na twój stacktrace, możesz zobaczyć 'at iaik.pkcs.pkcs1.RSACipher.engineInit (Unknown Source)'. Mój ma ten sam problem, tylko z innym dostawcą, 'Entrust'. Usuń tego dostawcę. – FaithReaper