दिलचस्प पोस्ट
वास्तव में एमईएफ एक डि आईओसी कंटेनर क्यों नहीं है? क्या डाक डेटा को अनुप्रेषित करना संभव है? मैं Windows बैच स्क्रिप्ट में फ़ाइल का आकार कैसे देख सकता / सकती हूं? एक टुकड़ा से एक गतिविधि विधि को बुलाओ पायथन वैरिएबल घोषणा कीबोर्ड को खारिज करने का आसान तरीका? ग्रहण के लिए सर्वश्रेष्ठ जीयूआई डिजाइनर? क्या कोई प्लेटफार्म है जहां विभिन्न प्रकार के संकेत दिए गए हैं? Google भाषण मान्यता समयबाह्य अजगर के सबप्रोसेक के लिए एक अच्छा समकक्ष क्या है। चेकमार्क stdout की सामग्री देता है? सी # क्रमबद्ध और क्रम तुलना करें हमें सी यूनियनों की आवश्यकता क्यों है? आईओएस 7 में नेविगेशन बार का रंग कैसे बदल सकता है? सी ++ में एक्सएमएल पार्सर का क्या उपयोग करना चाहिए? जवाफिक्स: स्थान त्रुटि सेट नहीं है

जावा HTTPS क्लाइंट प्रमाणन प्रमाणीकरण

मैं HTTPS / SSL / TLS में काफी नया हूँ और मैं थोड़ा उलझन में हूँ कि प्रमाणपत्रों के साथ प्रमाणीकरण करते समय वास्तव में ग्राहकों को क्या प्रस्तुत करना चाहिए।

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

मैं जानना चाहूंगा कि क्लाइंट को सर्वर के साथ प्रमाणित होने के साथ ही प्रमाण पत्र के साथ प्रमाणित करना चाहिए (विशेष रूप से जावा के लिए – यदि वह बिल्कुल मायने रखता है)? क्या यह एक जेकेएस फ़ाइल या पीकेसीएस # 12 है? उन में क्या होना चाहिए; बस क्लाइंट प्रमाण पत्र, या एक कुंजी? यदि हां, तो कौन सी कुंजी? सभी अलग-अलग प्रकार की फाइलों, प्रमाण पत्र प्रकारों और इस तरह के बारे में कुछ भ्रम है।

जैसा कि मैंने कहा है कि इससे पहले कि मैं एचटीटीपीएस / एसएसएल / टीएलएस के लिए नया हूँ, इसलिए मैं कुछ पृष्ठभूमि जानकारी की सराहना करता हूं (एक निबंध नहीं होना चाहिए, मैं अच्छे लेखों के लिंक के लिए समझौता करूंगा)।

वेब के समाधान से एकत्रित समाधान "जावा HTTPS क्लाइंट प्रमाणन प्रमाणीकरण"

अंत में सभी मुद्दों को हल करने में कामयाब रहे, इसलिए मैं अपने प्रश्न का उत्तर दूंगा। ये मेरी विशेष समस्याएं हल करने के लिए प्रबंधित करने वाली सेटिंग्स / फाइल हैं;

ग्राहक की कीस्टोर एक पीकेसीएस # 12 प्रारूप फाइल है जिसमें

  1. ग्राहक के सार्वजनिक प्रमाण पत्र (इस उदाहरण में एक स्व-हस्ताक्षरित सीए द्वारा हस्ताक्षरित)
  2. ग्राहक की निजी कुंजी

इसे उत्पन्न करने के लिए मैंने ओपनएसएसएल के pkcs12 कमांड का इस्तेमाल किया, उदाहरण के लिए;

 openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "Whatever" 

टिप: सुनिश्चित करें कि आप नवीनतम ओपनएसएसएल प्राप्त करें, संस्करण 0.9.8 एच नहीं है , क्योंकि ऐसा लगता है कि एक बग से पीड़ित है जो आपको पीकेसीएस # 12 फाइलों को ठीक से उत्पन्न करने की अनुमति नहीं देता है।

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

ग्राहक का ट्रस्टस्टोर एक सीधा आगे वाली जेकेएस फॉर्मेट फ़ाइल है जिसमें रूट या इंटरमीडिएट सीए प्रमाणपत्र शामिल हैं । ये सीए प्रमाण पत्र निर्धारित करेंगे कि आपको किस अंतराल के साथ संवाद करने की इजाजत होगी, इस मामले में यह आपके क्लाइंट को जो भी सर्वर से कनेक्ट करने की अनुमति देगा, वह एक प्रमाण पत्र प्रस्तुत करता है जिसे ट्रस्टस्टोर के सीए के किसी एक द्वारा हस्ताक्षरित किया गया था।

इसे बनाने के लिए आप मानक जावा कुंजी टोल का उपयोग कर सकते हैं, उदाहरण के लिए;

 keytool -genkey -dname "cn=CLIENT" -alias truststorekey -keyalg RSA -keystore ./client-truststore.jks -keypass whatever -storepass whatever keytool -import -keystore ./client-truststore.jks -file myca.crt -alias myca 

इस ट्रस्टस्टोअर का उपयोग करके, आपका क्लाइंट सभी एसआरएस हैंडशेक करने की कोशिश करेगा, जो कि myca.crt द्वारा पहचाने गए सीए द्वारा हस्ताक्षरित प्रमाणपत्र प्रस्तुत myca.crt

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

मुद्दों / टिप्पणियां / सुझाव

  1. क्लाइंट प्रमाणन प्रमाणीकरण केवल सर्वर द्वारा लागू किया जा सकता है
  2. ( महत्वपूर्ण! ) जब क्लाइंट क्लाइंट प्रमाणपत्र (टीएलएस हैंडशेक के भाग के रूप में) का अनुरोध करता है, तो यह प्रमाणपत्र अनुरोध के भाग के रूप में विश्वस्त सीए की एक सूची भी प्रदान करेगा। जब प्रमाणीकरण के लिए पेश करने वाला ग्राहक प्रमाण पत्र इन सीए में से किसी एक द्वारा हस्ताक्षरित नहीं होता है , तो यह बिल्कुल नहीं प्रस्तुत किया जाएगा (मेरी राय में, यह अजीब व्यवहार है, लेकिन मुझे यकीन है कि इसके लिए एक कारण है)। यह मेरे मुद्दों का मुख्य कारण था, क्योंकि अन्य पार्टी ने अपने स्वयं के हस्ताक्षरित क्लाइंट प्रमाणपत्र को स्वीकार करने के लिए अपने सर्वर को ठीक से कॉन्फ़िगर नहीं किया था और हमने यह मान लिया है कि समस्या मेरे अनुरोध पर क्लाइंट प्रमाणपत्र को ठीक से प्रदान करने के लिए नहीं थी।
  3. वायरसहार्क प्राप्त करें इसमें महान एसएसएल / एचटीटीपीएस पैकेट विश्लेषण है और यह बहुत ही उपयोगी डिबगिंग और समस्या का पता लगाएगा। -Djavax.net.debug=ssl के समान है लेकिन यदि आप जावा SSL डीबग आउटपुट के साथ असुविधाजनक हैं तो यह अधिक स्पष्ट और (यकीनन) व्याख्या करने में आसान है
  4. यह पूरी तरह संभव है कि अपाचे की वेबसाइट का उपयोग करें। यदि आप httpclient का उपयोग करना चाहते हैं, तो बस HTTPS समतुल्य के साथ गंतव्य यूआरएल को बदलें और निम्नलिखित जेवीएम तर्कों को जोड़ें (जो किसी भी अन्य क्लाइंट के लिए समान हैं, पुस्तकालय की परवाह किए बिना आप HTTP / HTTPS पर डेटा भेजने / प्राप्त करने के लिए उपयोग करना चाहते हैं) :

     -Djavax.net.debug=ssl -Djavax.net.ssl.keyStoreType=pkcs12 -Djavax.net.ssl.keyStore=client.p12 -Djavax.net.ssl.keyStorePassword=whatever -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStore=client-truststore.jks -Djavax.net.ssl.trustStorePassword=whatever 

वे JKS फ़ाइल सिर्फ प्रमाणपत्र और कुंजी जोड़े के लिए एक कंटेनर है। क्लाइंट-साइड प्रमाणीकरण परिदृश्य में, कुंजी के विभिन्न भागों यहां स्थित होंगे:

  • ग्राहक की दुकान में ग्राहक की निजी और सार्वजनिक कुंजी जोड़ी होगी इसे एक मुख्यस्टोर कहा जाता है
  • सर्वर की दुकान में ग्राहक की सार्वजनिक कुंजी होगी इसे ट्रस्टस्टोर कहा जाता है

ट्रस्टस्टोर और कीस्टोर की जुदाई अनिवार्य नहीं है बल्कि सिफारिश की जाती है। वे एक ही भौतिक फ़ाइल हो सकती हैं

दो स्टोरों के फाइल सिस्टम स्थानों को सेट करने के लिए, निम्न सिस्टम गुणों का उपयोग करें:

 -Djavax.net.ssl.keyStore=clientsidestore.jks 

और सर्वर पर:

 -Djavax.net.ssl.trustStore=serversidestore.jks 

क्लाइंट के प्रमाणपत्र (सार्वजनिक कुंजी) को किसी फ़ाइल में निर्यात करने के लिए, ताकि आप इसे सर्वर पर कॉपी कर सकें, उपयोग करें

 keytool -export -alias MYKEY -file publicclientkey.cer -store clientsidestore.jks 

क्लाइंट की सार्वजनिक कुंजी को सर्वर कीस्टस्टोर में आयात करने के लिए उपयोग करें (जैसा कि पोस्टर का उल्लेख है, यह पहले से ही सर्वर व्यवस्थापक द्वारा किया गया है)

 keytool -import -file publicclientkey.cer -store serversidestore.jks 

अन्य जवाब बताते हैं कि क्लाइंट प्रमाण पत्र को विश्व स्तर पर कॉन्फ़िगर कैसे करें। हालांकि यदि आप प्रोग्राम को एक विशेष कनेक्शन के लिए क्लाइंट कुंजी को परिभाषित करना चाहते हैं, तो वैश्विक स्तर पर इसे अपने जेवीएम पर चलने वाले सभी एप्लिकेशन में परिभाषित करने के बजाय, आप अपने SSLContext को इस तरह कॉन्फ़िगर कर सकते हैं:

 String keyPassphrase = ""; KeyStore keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(new FileInputStream("cert-key-pair.pfx"), keyPassphrase.toCharArray()); SSLContext sslContext = SSLContexts.custom() .loadKeyMaterial(keyStore, null) .build(); HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build(); HttpResponse response = httpClient.execute(new HttpGet("https://example.com")); 

मेवेन पॉम। एक्सएमएल:

 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>some.examples</groupId> <artifactId>sslcliauth</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>sslcliauth</name> <dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.4</version> </dependency> </dependencies> </project> 

जावा कोड:

 package some.examples; import java.io.FileInputStream; import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.logging.Level; import java.util.logging.Logger; import javax.net.ssl.SSLContext; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.ssl.SSLContexts; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.apache.http.entity.InputStreamEntity; public class SSLCliAuthExample { private static final Logger LOG = Logger.getLogger(SSLCliAuthExample.class.getName()); private static final String CA_KEYSTORE_TYPE = KeyStore.getDefaultType(); //"JKS"; private static final String CA_KEYSTORE_PATH = "./cacert.jks"; private static final String CA_KEYSTORE_PASS = "changeit"; private static final String CLIENT_KEYSTORE_TYPE = "PKCS12"; private static final String CLIENT_KEYSTORE_PATH = "./client.p12"; private static final String CLIENT_KEYSTORE_PASS = "changeit"; public static void main(String[] args) throws Exception { requestTimestamp(); } public final static void requestTimestamp() throws Exception { SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory( createSslCustomContext(), new String[]{"TLSv1"}, // Allow TLSv1 protocol only null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(csf).build()) { HttpPost req = new HttpPost("https://changeit.com/changeit"); req.setConfig(configureRequest()); HttpEntity ent = new InputStreamEntity(new FileInputStream("./bytes.bin")); req.setEntity(ent); try (CloseableHttpResponse response = httpclient.execute(req)) { HttpEntity entity = response.getEntity(); LOG.log(Level.INFO, "*** Reponse status: {0}", response.getStatusLine()); EntityUtils.consume(entity); LOG.log(Level.INFO, "*** Response entity: {0}", entity.toString()); } } } public static RequestConfig configureRequest() { HttpHost proxy = new HttpHost("changeit.local", 8080, "http"); RequestConfig config = RequestConfig.custom() .setProxy(proxy) .build(); return config; } public static SSLContext createSslCustomContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException { // Trusted CA keystore KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE); tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray()); // Client keystore KeyStore cks = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE); cks.load(new FileInputStream(CLIENT_KEYSTORE_PATH), CLIENT_KEYSTORE_PASS.toCharArray()); SSLContext sslcontext = SSLContexts.custom() //.loadTrustMaterial(tks, new TrustSelfSignedStrategy()) // use it to customize .loadKeyMaterial(cks, CLIENT_KEYSTORE_PASS.toCharArray()) // load client certificate .build(); return sslcontext; } } 

उन लोगों के लिए जो केवल दो-तरफा प्रमाणीकरण (सर्वर और क्लाइंट प्रमाण पत्र) को सेट करना चाहते हैं, इन दोनों लिंक के संयोजन आपको वहां मिलेगा:

दो-मार्ग प्रमाणन सेटअप:

https://linuxconfig.org/apache-web-server-ssl-authentication

आपको खोलने वाले openssl config फ़ाइल का उपयोग करने की आवश्यकता नहीं है; महज प्रयोग करें

  • $ openssl genrsa -des3 -out ca.key 4096

  • $ openssl req -new -x509- दिन 365 -key ca.key -out ca.crt

अपना स्वयं का सीए प्रमाण पत्र तैयार करने के लिए, और उसके बाद सर्वर और क्लाइंट कुंजी को उत्पन्न और हस्ताक्षर करें:

  • $ openssl genrsa -des3 -out server.key 4096

  • $ openssl req -new -key client.key -out server.csr

  • $ openssl x509 -राक -दिन 365 -इन सर्वर। सीएसआर -सीए ca.crt -कैची ca.key -set_serial 100-आउट server.crt

तथा

  • $ openssl genrsa -des3- क्लाइंट.की 4096

  • $ openssl req -new -key क्लाइंट .key -out client.csr

  • $ openssl x509 -रेक -दिन 365 -इन क्लाइंट। csr -CA ca.crt -Ckey ca.key -set_serial 101 -अगर client.crt

बाकी के लिए लिंक में दिए गए चरणों का पालन करें क्रोम के लिए प्रमाणपत्र प्रबंधित करना फ़ायरफ़ॉक्स के लिए उदाहरण के जैसा ही काम करता है जिसका उल्लेख है।

इसके बाद, सर्वर के माध्यम से सेटअप करें:

https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-certificate-on-apache-for-ubuntu-14-04

ध्यान दें कि आपने पहले ही .crt और .key सर्वर बनाया है, इसलिए आपको उस चरण को अब और करना नहीं पड़ता है

मुझे लगता है कि ठीक यहाँ मुख्य प्रकार का था, pkcs12 (पीएफएक्स) हमेशा निजी कुंजी है और निजी कुंजी के बिना JKS प्रकार मौजूद हो सकता है जब तक आप अपने कोड में निर्दिष्ट नहीं करते हैं या ब्राउज़र के माध्यम से एक प्रमाण पत्र का चयन करते हैं, तो सर्वर को यह जानने का कोई तरीका नहीं है कि वह दूसरे छोर पर ग्राहक का प्रतिनिधित्व कर रहा है।