2012-07-31 13 views
7

में सर्वर पर एक प्रमाणपत्र वापस नहीं भेज रहा है जावा 77 में एक जावा 1.7 ऐप चल रहा है, मैं एक सर्वर के साथ 2-तरफा एसएसएल करने की कोशिश कर रहा हूं (ए स्मार्टकार्ड टोकन ओपनएससी के माध्यम से अपने क्लाइंट कॉर्ट प्रदान कर रहा है)। सर्वर का प्रमाणपत्र क्लाइंट द्वारा ठीक से सत्यापित हो रहा है, लेकिन क्लाइंट सर्वर के प्रमाणपत्र अनुरोध का जवाब नहीं देता है। मेरा मानना ​​है कि ऐसा इसलिए है क्योंकि क्लाइंट सर्वर से अनुरोध किए गए किसी एक को मेरे प्रमाणपत्र से एक श्रृंखला बनाने में सक्षम नहीं है (भले ही ऐसी श्रृंखला मौजूद है)।मेरा एसएसएल क्लाइंट (जावा) दो-तरफा एसएसएल हैंडशेक

*** CertificateRequest 
Cert Types: RSA, DSS, ECDSA 
Cert Authorities: 
<CN=c4isuite-SDNI-DC02-CA, DC=c4isuite, DC=local> 
<CN=DoD Root CA 2, OU=PKI, OU=DoD, O=U.S. Government, C=US> 
    ... 
*** ServerHelloDone 
*** Certificate chain 
*** 

मेरे क्लाइंट प्रमाणपत्र इस प्रकार है::

found key for : Certificate for PIV Authentication 
chain [0] = [ 
[ 
    Version: V3 
    Subject: CN=<...>, OU=CONTRACTOR, OU=PKI, OU=DoD, O=U.S. Government, C=US 
    Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5 

    Key: Sun RSA public key, 2048 bits 

    Issuer: CN=DOD CA-30, OU=PKI, OU=DoD, O=U.S. Government, C=US 
    SerialNumber: [ 05bf13] 

वाया कुंजी उपकरण, मैं भी में स्थापित

यहाँ सर्वर का प्रमाणपत्र अनुरोध की एसएसएल डिबग और ग्राहकों खाली प्रतिक्रिया है ट्रस्टस्टोर (जावा कैकर्ट्स फ़ाइल), मेरे प्रमाणक के जारीकर्ता, डीओडी सीए -30, और सर्वर क्या अनुरोध कर रहा है, के बीच लिंक होना चाहिए, डीओडी रूट सीए 2.

एसएसएल डीबग से:

adding as trusted cert: 
    Subject: CN=DOD CA-30, OU=PKI, OU=DoD, O=U.S. Government, C=US 
    Issuer: CN=DoD Root CA 2, OU=PKI, OU=DoD, O=U.S. Government, C=US 
    Algorithm: RSA; Serial number: 0x1b5 
    Valid from Thu Sep 08 10:59:24 CDT 2011 until Fri Sep 08 10:59:24 CDT 2017 

adding as trusted cert: 
    Subject: CN=DoD Root CA 2, OU=PKI, OU=DoD, O=U.S. Government, C=US 
    Issuer: CN=DoD Root CA 2, OU=PKI, OU=DoD, O=U.S. Government, C=US 
    Algorithm: RSA; Serial number: 0x5 
    Valid from Mon Dec 13 09:00:10 CST 2004 until Wed Dec 05 09:00:10 CST 2029 

तो प्रश्न यह है कि क्लाइंट प्रतिक्रिया के लिए प्रमाणपत्र श्रृंखला क्यों नहीं बना सकता? यहाँ प्रासंगिक कोड है:

// Create the keyStore from the SmartCard certs 
    Provider provider = new sun.security.pkcs11.SunPKCS11(configName); 

    Security.addProvider(provider); 
    keyStore = KeyStore.getInstance("PKCS11", "SunPKCS11-SCR3310test"); 
    char[] pin = PIN.toCharArray(); 
    keyStore.load(null, pin); 

     // Init the trustmanager 
     TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
     tmf.init(trustStore); 

     // Create the client key manager 
     LOG.info("Installing keystore with pin"); 
     KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); 
     keyManagerFactory.init(clientKeyStore, clientKeyPassword.toCharArray());   

     sslContext.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null); 

     // Init SSL context 
     SSLSocketFactory socketFactory = sslContext.getSocketFactory(); 


     URL url = new URL(urlString); 
     URLConnection connection = url.openConnection(); 
     if (connection instanceof HttpsURLConnection) { 
      LOG.info("Connection is HTTPS"); 
      ((HttpsURLConnection) connection).setSSLSocketFactory(socketFactory); 
     } 

     // Send the request. 
     connection.connect(); 

     InputStreamReader in = new InputStreamReader((InputStream) connection.getContent()); 
     ... 

और त्रुटि मैं वापस पाने कि सर्वर की ओर एक 403 सबसे अधिक संभावना है क्योंकि क्लाइंट यह एक ग्राहक प्रमाणपत्र नहीं भेजा है।

उत्तर

3

भले ही ऐसा लगता है कि आपने इस प्रश्न में सर्वर द्वारा भेजे गए सीए सूची का हिस्सा केवल कॉपी किया है, तो मुझे लगता है कि CN=DOD CA-30, OU=PKI, OU=DoD, O=U.S. Government, C=US इस सूची में नहीं है।

क्या श्रृंखला में कमी रह गई है इस प्रमाणपत्र (जो आप बाद में उल्लेख) है:

Subject: CN=DOD CA-30, OU=PKI, OU=DoD, O=U.S. Government, C=US 
    Issuer: CN=DoD Root CA 2, OU=PKI, OU=DoD, O=U.S. Government, C=US 
    Algorithm: RSA; Serial number: 0x1b5 
    Valid from Thu Sep 08 10:59:24 CDT 2011 until Fri Sep 08 10:59:24 CDT 2017 

अपने ग्राहक की truststore में प्रमाण पत्र का आयात प्रमाण पत्र ग्राहक भेजता है पर बिल्कुल कोई प्रभाव नहीं है। ग्राहक-प्रमाणपत्र (और इसकी निजी कुंजी) को क्लाइंट कीस्टोर में स्थापित करने की आवश्यकता है। इसके अतिरिक्त, यदि आप क्लाइंट-सर्टिफिकेट चेन भेजना चाहते हैं (जो यहां आवश्यक होगा, यदि सर्वर अपनी इंटरमीडिएट सीए प्रमाणपत्र को इसकी सूची में पेश नहीं करता है), तो आपको पूर्ण श्रृंखला को उस प्रमाणपत्र प्रविष्टि में जोड़ना होगा। अन्य प्रमाणपत्रों को कीस्टोर में रखना पर्याप्त नहीं है।

इसे ठीक करने के लिए, आपको क्लाइंट-प्रमाणपत्र श्रृंखला के साथ अपनी कीस्टोर प्रविष्टि को कॉन्फ़िगर करना चाहिए। यह this answer में वर्णित के रूप में किया जा सकता है। हालांकि, यह संभव है कि यह तथ्य है कि यह पीकेसीएस # 11 के माध्यम से उपयोग किए जाने वाले हार्डवेयर टोकन को थोड़ा और जटिल बना सकता है (शायद कार्ड के साथ प्रदान किया गया एक और प्रमाण पत्र प्रबंधन उपकरण है, जो जावा से संभवतः स्वतंत्र है)।

+0

मुझे सीधे प्रमाण पत्र श्रृंखला खोजने के लिए ट्रस्ट स्टोर का उपयोग न करने वाले क्लाइंट पर सेट करने के लिए धन्यवाद। चूंकि प्रमाणपत्र स्मार्टकार्ड से है, इसलिए प्रमाण को संशोधित करना मुश्किल या असंभव है। मैंने इसे एक और तरीके से प्राप्त करने का प्रबंधन किया, जिसे मैंने नीचे जवाब के रूप में विस्तृत किया, ताकि एक ही स्थिति में किसी और के पास जवाब हो। – PaulP

2

के बाद से मैं जानता हूँ कि जो प्रमाण पत्र मैं सर्वर से प्रमाणीकरण के लिए उपयोग करने की आवश्यकता है, मैं X509ExtendedKeyManager का विस्तार, और chooseClientAlias ​​ओवरराइड() विधि हमेशा उस प्रमाण पत्र की उर्फ ​​वापस जाने के लिए द्वारा उस विशिष्ट प्रमाण पत्र भेजने के लिए ग्राहक के लिए मजबूर कर सकते हैं। कोड:

public class MyX509KeyManager extends X509ExtendedKeyManager 
    { 
    X509KeyManager defaultKeyManager; 

    public MyX509KeyManager(X509KeyManager inKeyManager) { 
     defaultKeyManager = inKeyManager; 
    } 

    public String chooseEngineClientAlias(String[] keyType, 
      Principal[] issuers, SSLEngine engine) { 
     return "<Alias of my cert>"; 
    } 

    @Override 
    public String chooseClientAlias(String[] strings, Principal[] prncpls, Socket socket) { 
     return "<Alias of my cert>"; 
    } 

    @Override 
    public String[] getClientAliases(String string, Principal[] prncpls) { 
     return defaultKeyManager.getClientAliases(string, prncpls); 
    } 

    @Override 
    public String[] getServerAliases(String string, Principal[] prncpls) { 
     return defaultKeyManager.getServerAliases(string, prncpls); 
    } 

    ... 

तो जैसा कि आप देख सकते हैं, मैं एक defaultKeyManager जो मैं मैं क्या ओवरराइड करना चाहते अलावा कुछ के लिए करने के लिए स्थगित में ले लो।फिर, अपने एसएसएल कॉन्टेक्स्ट में इसका उपयोग करने के लिए, निम्न कार्य करें:

// clientKeyStore is initialized elsewhere from the SmartCard 
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); 
keyManagerFactory.init(clientKeyStore, clientKeyPassword.toCharArray()); 

MyX509KeyManager customKeyManager = new MyX509KeyManager((X509KeyManager) keyManagerFactory.getKeyManagers()[0]); 
sslContext.init(new KeyManager[] {customKeyManager}, tmf.getTrustManagers(), null); 
+1

क्लाइंट को यह प्रमाण पत्र भेजने के लिए यह समझ में आता है, लेकिन अगर सर्वर को सत्यापित करने के लिए सर्वर बनाने के लिए इंटरमीडिएट प्रमाणपत्र खो रहा है तो लगभग निश्चित रूप से समस्या होगी। (यह केवल तभी काम कर सकता है जब सर्वर इंटरमीडिएट सर्टिफिकेट से अवगत हो, लेकिन प्रमाण पत्र अनुरोध संदेश में अपना नाम नहीं भेजता है, जो संभव है।) – Bruno

+0

आप यह भी कर सकते हैं कि इस प्रमाणपत्र को जोड़ने के लिए 'getCertificateChain' को ओवरराइड करना है श्रृंखला मैन्युअल रूप से। – Bruno

+0

सही, यह मान रहा है कि सर्वर में पूर्ण प्रमाणपत्र श्रृंखला उपलब्ध है। – PaulP

संबंधित मुद्दे