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


222

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

मैं एक जावा क्लाइंट लिख रहा हूं जिसे POSTकिसी विशेष डेटा को सरल करने की आवश्यकता है URL। यह हिस्सा ठीक काम करता है, केवल समस्या यह है कि इसे खत्म किया जाना चाहिए HTTPSHTTPSहिस्सा संभाल करने के लिए काफी आसान है (या तो साथ HTTPclientया का उपयोग कर जावा के अंतर्निहित HTTPSसमर्थन), लेकिन मुझे क्लाइंट प्रमाण पत्र को प्रमाणित करने पर अटक कर रहा हूँ। मैंने देखा है कि यहाँ पहले से ही एक समान प्रश्न है, जिसे मैंने अभी तक अपने कोड के साथ आज़माया नहीं है (यह इतनी जल्दी कर देगा)। मेरा वर्तमान मुद्दा यह है कि - मैं जो कुछ भी करता हूं - जावा क्लाइंट कभी भी प्रमाण पत्र के साथ नहीं भेजता है (मैं इसे PCAPडंप के साथ जांच सकता हूं )।

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

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


मैं ग्राहक से दो प्रमाण पत्र दे दिया है जो एक की जरूरत है कुंजीस्टोर में जोड़ने के लिए पहचान करने के लिए कैसे और truststore आप को खुश कर सकता है मदद इस मुद्दे की पहचान के रूप में आप पहले से ही जारी किए जाने की समान प्रकार के माध्यम से चले गए हैं, इस मुद्दे को मैं वास्तव में उठाया है सुराग क्या करना है नहीं मिल रहा है stackoverflow .com / सवाल / 61374276 /…
henrycharles

जवाबों:


233

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

ग्राहक की कुंजीस्टोर एक है PKCS # 12 प्रारूप वाली फ़ाइल

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

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

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

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

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

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

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

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

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

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

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

6
"जब आपके द्वारा प्रमाणीकरण के लिए प्रस्तुत किए जाने वाले ग्राहक प्रमाणपत्र पर इनमें से किसी एक सीए द्वारा हस्ताक्षरित नहीं किया जाता है, तो उसे प्रस्तुत नहीं किया जाएगा"। प्रमाणपत्र प्रस्तुत नहीं किए जाते हैं क्योंकि ग्राहक को पता है कि वे सर्वर द्वारा स्वीकार नहीं किए जाएंगे। इसके अलावा, आपके प्रमाणपत्र पर एक मध्यवर्ती CA "ICA" द्वारा हस्ताक्षरित किया जा सकता है, और सर्वर आपके क्लाइंट को रूट CA "RCA" के साथ प्रस्तुत कर सकता है, और आपका वेब ब्राउज़र अभी भी आपको ICA नहीं RCA द्वारा हस्ताक्षरित होने के बावजूद अपना प्रमाणपत्र लेने देगा।
काइलएम

2
उपरोक्त टिप्पणी के एक उदाहरण के रूप में, ऐसी स्थिति पर विचार करें जहां आपके पास एक रूट CA (RCA1) और दो मध्यवर्ती CA (ICA1 और ICA2) हैं। अगर आप RCA1 को ट्रस्ट स्टोर में आयात करते हैं तो Apache Tomcat पर, आपका वेब ब्राउज़र ICA1 और ICA2 द्वारा हस्ताक्षरित सभी प्रमाणपत्र प्रस्तुत करेगा, भले ही वे आपके ट्रस्ट स्टोर में न हों। ऐसा इसलिए है क्योंकि यह वह श्रृंखला है जो किसी भी व्यक्ति के लिए महत्वपूर्ण नहीं है।
काइलएम

2
"मेरी राय में, यह अजीब व्यवहार है, लेकिन मुझे यकीन है कि इसके लिए एक कारण है"। इसका कारण यह है कि यह आरएफसी 2246 में कहता है। इसके बारे में कुछ भी अजीब नहीं है। ग्राहकों को प्रमाण पत्र प्रस्तुत करने की अनुमति देना जो सर्वर द्वारा स्वीकार नहीं किया जाएगा, वह अजीब होगा, और समय और स्थान की पूरी बर्बादी होगी।
लोर्ने

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

63

अन्य उत्तर दिखाते हैं कि विश्व स्तर पर क्लाइंट सर्टिफिकेट कैसे कॉन्फ़िगर किए जाते हैं। हालाँकि, यदि आप अपने JVM पर चल रहे हर एप्लिकेशन को वैश्विक रूप से परिभाषित करने के बजाय किसी विशेष कनेक्शन के लिए क्लाइंट कुंजी को प्रोग्राम करना चाहते हैं, तो आप अपने 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"));

मुझे इस्तेमाल करना था sslContext = SSLContexts.custom().loadTrustMaterial(keyFile, PASSWORD).build();। मैं इसके साथ काम नहीं कर सका loadKeyMaterial(...)
कॉनर स्वेंसन

4
@ConorSvensson ट्रस्ट सामग्री दूरस्थ सर्वर प्रमाणपत्र पर भरोसा करने वाले क्लाइंट के लिए है, कुंजी सामग्री क्लाइंट पर भरोसा करने वाले सर्वर के लिए है।
मैग्नस

1
मुझे यह संक्षिप्त और ऑन-पॉइंट उत्तर पसंद है। यदि लोग रुचि रखते हैं, तो मैं निर्माण निर्देशों के साथ यहां एक उदाहरण दिया गया हूं। stackoverflow.com/a/46821977/154527
Alain O'Dea

3
आपने मेरा दिन बचाया! बस एक अतिरिक्त परिवर्तन मुझे करना था, loadKeyMaterial(keystore, keyPassphrase.toCharArray())कोड 'में भी पासवर्ड भेजें !
आनंदभानग

1
@peterh हाँ यह अपाचे http के लिए विशिष्ट है। हर HTTP लाइब्रेरी को कॉन्फ़िगर करने का अपना तरीका होगा, लेकिन उनमें से अधिकांश को किसी न किसी तरह से उपयोग करना चाहिए SSLContext
मैग्नस

30

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

  • ग्राहक की दुकान ग्राहक के शामिल होंगे निजी और सार्वजनिक कुंजी युग्म। इसे कीस्टोर कहा जाता है ।
  • सर्वर की दुकान ग्राहक के शामिल होंगे सार्वजनिक कुंजी। इसे ट्रस्टस्टोर कहा जाता है ।

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

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

-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

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

आपको अपने सार्वजनिक प्रमाण पत्र के लिए सार्वजनिक और निजी कुंजी की आवश्यकता होगी (जो कि सर्वर के लिए जाना जाता है) जेकेएस फ़ाइल के रूप में।
sfussenegger

उदाहरण कोड के लिए धन्यवाद। उपरोक्त कोड में, "mykey-public.cer" क्या है? क्या यह ग्राहक सार्वजनिक प्रमाणपत्र है (हम स्व-हस्ताक्षरित प्रमाणपत्र का उपयोग करते हैं)?
tmbrggmn

हाँ यह है, मैं कोड स्निपेट में फ़ाइलों का नाम बदल दिया है तदनुसार। मुझे उम्मीद है कि यह स्पष्ट हो जाएगा।
mhaller 8

राइटो, धन्यवाद। मैं भ्रमित हो रहा हूं क्योंकि स्पष्ट रूप से "कुंजी" और "प्रमाण पत्र" का उपयोग पारस्परिक रूप से किया जाता है।
tmbrggmn

10

मावेन pom.xml:

<?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;
}

}

यदि आपके पास किसी विशेष JVM इंस्टॉलेशन का उपयोग करने वाले सभी अनुप्रयोगों के लिए प्रमाण पत्र उपलब्ध है, तो इसके बजाय इस उत्तर का पालन करें
ADTC

configureRequest()क्लाइंट प्रोजेक्ट के प्रॉक्सी को सही तरीके से सेट करने की विधि है ?
शायर

हां, यह http क्लाइंट कॉन्फ़िगरेशन है और यह इस मामले में प्रॉक्सी कॉन्फिग है
kinjelom

शायद मेरे पास एक गूंगा सवाल है, लेकिन मैं फ़ाइल cacert.jks कैसे बनाऊं? मेरे पास अपवाद अपवाद "थ्रेड" मुख्य "java.io.FileNotFoundException:। \ Cacert.jks (सिस्टम निर्दिष्ट फ़ाइल नहीं ढूँढ सकता है)
Patlatus

6

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

दो-तरफा ऑर्ट सेटअप:

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

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

  • $ खुलता है genrsa -des3 -out ca.key 4096

  • $ opensl req -new -x509 -days 365 -key ca.key -out ca.crt

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

  • $ खुलता है genrsa -des3 -out server.key 4096

  • $ opensl req -new -key server.key -out server.csr

  • $ opensl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 100 -out server.crt

तथा

  • $ खुलता है genrsa -des3 -out client.key 4096

  • $ opensl req -new -key client.key -out client.csr

  • $ opensl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 101 -out client.crt

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

अगला, सर्वर को इसके माध्यम से सेटअप करें:

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

ध्यान दें कि आपने पहले ही सर्वर .crt और .key बना लिया है, इसलिए आपको वह कदम अब और नहीं करना है।


1
आपको लगता है कि आपके पास सर्वर CSR जनरेशन स्टेप में टाइपो है: server.keyclient.key
बजे

0

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

  1. सर्टिफिकेट अनुरोध उत्पन्न करें:

    • निजी कुंजी उत्पन्न करें:

      openssl genrsa -des3 -passout pass:MY_PASSWORD -out user.key 2048
    • प्रमाणपत्र अनुरोध उत्पन्न करें:

      openssl req -new -key user.key -out user.csr -passin pass:MY_PASSWORD

    user.key(पासवर्ड और पासवर्ड) रखें और user.csrमेरे सर्टिफिकेट के लिए बैंक को प्रमाणपत्र अनुरोध भेजें

  2. 2 प्रमाणपत्र प्राप्त करें: मेरा क्लाइंट रूट प्रमाणपत्र clientId.crtऔर बैंक रूट प्रमाणपत्र:bank.crt

  3. जावा कीस्टोर बनाएँ (कुंजी पासवर्ड दर्ज करें और कीस्टोर पासवर्ड सेट करें):

    openssl pkcs12 -export -in clientId.crt -inkey user.key -out keystore.p12 -name clientId -CAfile ca.crt -caname root

    आउटपुट पर ध्यान न दें unable to write 'random state':। Java PKCS12 keystore.p12बनाया गया।

  4. कीस्टोर में जोड़ें bank.crt(सादगी के लिए मैंने एक कीस्टोर का उपयोग किया है):

    keytool -import -alias banktestca -file banktestca.crt -keystore keystore.p12 -storepass javaops

    कीस्टॉर प्रमाणपत्र की जाँच करें:

    keytool -list -keystore keystore.p12
  5. जावा कोड के लिए तैयार :) मैंने RestTemplateऐड org.apache.httpcomponents.httpcoreनिर्भरता के साथ स्प्रिंग बूट का उपयोग किया है :

    @Bean("sslRestTemplate")
    public RestTemplate sslRestTemplate() throws Exception {
      char[] storePassword = appProperties.getSslStorePassword().toCharArray();
      URL keyStore = new URL(appProperties.getSslStore());
    
      SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(keyStore, storePassword)
      // use storePassword twice (with key password do not work)!!
            .loadKeyMaterial(keyStore, storePassword, storePassword) 
            .build();
    
      // Solve "Certificate doesn't match any of the subject alternative names"
      SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    
      CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
      HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
      RestTemplate restTemplate = new RestTemplate(factory);
      // restTemplate.setMessageConverters(List.of(new Jaxb2RootElementHttpMessageConverter()));
      return restTemplate;
    }

आप यह सब कर सकते हैं keytool के साथ। इस में forOpenSSL की कोई आवश्यकता नहीं है।
लोर्ने

0

प्रमाण पत्र और निजी कुंजी (उदाहरण के लिए, ओपनएसएल द्वारा उत्पन्न) दोनों के साथ एक पी 12 फ़ाइल को देखते हुए, निम्न कोड एक विशिष्ट HttpsURLConnection के लिए उपयोग करेगा:

    KeyStore keyStore = KeyStore.getInstance("pkcs12");
    keyStore.load(new FileInputStream(keyStorePath), keystorePassword.toCharArray());
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(keyStore, keystorePassword.toCharArray());
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(kmf.getKeyManagers(), null, null);
    SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    connection.setSSLSocketFactory(sslSocketFactory);

SSLContext, प्रारंभ करने में कुछ समय लगता है, तो आप इसे कैश करने के लिए चाहते हो सकता है।


-1

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


1
PKCS12 प्रारूप पारंपरिक रूप से प्राइवेटकी-एंड-सर्टिफिकेट के लिए उपयोग किया गया था, लेकिन 2014 में 8 के बाद से जावा (इस उत्तर से पहले एक वर्ष से अधिक) ने PKCS12 को प्राइवेटकी (s) के बिना सर्टिफिकेट (s) युक्त समर्थन दिया है। कीस्टॉर प्रारूप के बावजूद, क्लाइंट ऑर्किटी को प्राइवेटकी-एंड-सर्टिफिकेट की आवश्यकता होती है। मैं अपने दूसरे वाक्य समझ में नहीं आता है, लेकिन जावा ग्राहक कर सकते हैं स्वचालित रूप से एक ग्राहक प्रमाणपत्र और कुंजी का चयन करता है, तो कम से कम एक उपयुक्त प्रविष्टि उपलब्ध है या एक keymanager कर सकते हैं एक निर्धारित एक का उपयोग करने के लिए कॉन्फ़िगर किया।
dave_thompson_085

आपका दूसरा वाक्य पूरी तरह से गलत है। सर्वर अपने विश्वसनीय हस्ताक्षरकर्ता प्रदान करता है, और क्लाइंट या तो मर जाता है या एक प्रमाणपत्र प्रदान नहीं करता है जो उस बाधा को पूरा करता है। स्वचालित रूप से, 'आपके कोड में' के माध्यम से नहीं। यही कारण है कि है सर्वर का 'जानने यह एक ग्राहक का प्रतिनिधित्व कर रहा है के रास्ते'।
लोर्ने का मार्विस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.