এইচটিটিপিএস / এসএসএলে জাভা ক্লায়েন্টের শংসাপত্রগুলি


116

আমি জাভা 6 ব্যবহার করছি এবং HttpsURLConnectionক্লায়েন্ট শংসাপত্র ব্যবহার করে একটি রিমোট সার্ভারের বিরুদ্ধে একটি তৈরি করার চেষ্টা করছি ।
সার্ভারটি স্ব-স্বাক্ষরিত মূল শংসাপত্র ব্যবহার করছে এবং এটি প্রয়োজন যে একটি পাসওয়ার্ড-সুরক্ষিত ক্লায়েন্ট শংসাপত্র উপস্থাপন করা হবে। আমি সার্ভারের রুট শংসাপত্র এবং ক্লায়েন্ট শংসাপত্রটি ডিফল্ট জাভা কীস্টোরের মধ্যে পেয়েছি যা আমি পেয়েছি /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/security/cacerts(ওএসএক্স 10.5) কীস্টোর ফাইলটির নাম মনে হচ্ছে যে ক্লায়েন্টের শংসাপত্রটি সেখানে যাওয়ার কথা নয়?

যাইহোক, এই স্টোরটিতে মূল শংসাপত্র যুক্ত করা কুখ্যাত সমাধান করেছে javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed' problem.

তবে, ক্লায়েন্টের শংসাপত্র কীভাবে ব্যবহার করতে হয় সে সম্পর্কে আমি এখন আটকে আছি। আমি দুটি পদ্ধতির চেষ্টা করেছি এবং আমাকে কোথাও পাই না।
প্রথমে এবং পছন্দসই, চেষ্টা করুন:

SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
URL url = new URL("https://somehost.dk:3049");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sslsocketfactory);
InputStream inputstream = conn.getInputStream();
// The last line fails, and gives:
// javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

আমি এইচটিটিপিআরএলস কানেকশন ক্লাসটি এড়িয়ে যাওয়ার চেষ্টা করেছি (যেহেতু আমি সার্ভারের সাথে এইচটিটিপি কথা বলতে চাই তাই আদর্শ নয়), এবং পরিবর্তে এটি করুন:

SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("somehost.dk", 3049);
InputStream inputstream = sslsocket.getInputStream();
// do anything with the inputstream results in:
// java.net.SocketTimeoutException: Read timed out

ক্লায়েন্ট শংসাপত্র এখানে সমস্যা যে আমি এমনকি নিশ্চিত নই।


আমি ক্লায়েন্ট থেকে দুই শংসাপত্র দেওয়া আছে যা এক চাহিদা কীস্টোর মধ্যে যোগ করার জন্য চিহ্নিত করতে কিভাবে এবং truststore আপনাকে সাহায্য করবে এই সমস্যা চিহ্নিত হিসাবে আপনি ইতিমধ্যে সংখ্যার অনুরূপ ধরনের মধ্য দিয়ে চলে গেছে খুশি পারে stackoverflow.com/questions/61374276/...
henrycharles

উত্তর:


100

শেষ পর্যন্ত এটি সমাধান করুন;)। এখানে শক্তিশালী ইঙ্গিত পেয়েছে (গ্যান্ডালফসের উত্তরও এতে কিছুটা স্পর্শ করেছে)। নিখোঁজ লিঙ্কগুলি (বেশিরভাগ ক্ষেত্রে) নীচের প্যারামিটারগুলির মধ্যে প্রথম ছিল এবং কিছুটা হলেও আমি কীস্টোরগুলি এবং ট্রস্টস্টোরগুলির মধ্যে পার্থক্যটিকে উপেক্ষা করেছি।

স্ব-স্বাক্ষরিত সার্ভার শংসাপত্র অবশ্যই একটি ট্রাস্টস্টোরে আমদানি করতে হবে:

কীটল-ইম্পোর্ট -ালিয়াস গ্রিডারভার -ফাইলে গ্রিডারভার.সিআরটি-স্টোরপাস $ পাস -কিস্টোর গ্রিডারভার.কিস্টোর

এই বৈশিষ্ট্যগুলি সেট করা দরকার (হয় কমান্ডলাইনে, অথবা কোডে):

-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.keyStore=clientcertificate.p12
-Djavax.net.ssl.trustStore=gridserver.keystore
-Djavax.net.debug=ssl # very verbose debug
-Djavax.net.ssl.keyStorePassword=$PASS
-Djavax.net.ssl.trustStorePassword=$PASS

কার্যকারী উদাহরণ কোড:

SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
URL url = new URL("https://gridserver:3049/cgi-bin/ls.py");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sslsocketfactory);
InputStream inputstream = conn.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

String string = null;
while ((string = bufferedreader.readLine()) != null) {
    System.out.println("Received " + string);
}

আমি একটি ইউআরএল ব্যবহার করেছি যেমন: লোকালহোস্ট: ৮৪৪৪ / অ্যাপ্লিকেশন_নাম / getAttributes । ইউআরএল ম্যাপিং / getAttribute সহ আমার একটি পদ্ধতি রয়েছে। এই পদ্ধতিটি উপাদানগুলির একটি তালিকা প্রদান করে। আমি এইচটিটিপিএসআরল সংযোগটি ব্যবহার করেছি, সংযোগ রেপোনস কোডটি 200, তবে এটি যখন আমাকে ইনপুটস্ট্রিম ব্যবহার করে তখন আমাকে বৈশিষ্ট্য তালিকা দেয় না, এটি আমার লগইন পৃষ্ঠার এইচটিএমএল সামগ্রী সরবরাহ করে। আমি প্রমাণীকরণ করেছি এবং বিষয়বস্তুর প্রকারটিকে JSON হিসাবে সেট করেছি। দয়া করে পরামর্শ দিন
দীপক

83

প্রস্তাবিত না হলেও আপনি এসএসএল শংসাপত্রের বৈধতা পুরোপুরি অক্ষম করতে পারেন:

import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

public class SSLTool {

  public static void disableCertificateValidation() {
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] { 
      new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() { 
          return new X509Certificate[0]; 
        }
        public void checkClientTrusted(X509Certificate[] certs, String authType) {}
        public void checkServerTrusted(X509Certificate[] certs, String authType) {}
    }};

    // Ignore differences between given hostname and certificate hostname
    HostnameVerifier hv = new HostnameVerifier() {
      public boolean verify(String hostname, SSLSession session) { return true; }
    };

    // Install the all-trusting trust manager
    try {
      SSLContext sc = SSLContext.getInstance("SSL");
      sc.init(null, trustAllCerts, new SecureRandom());
      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
      HttpsURLConnection.setDefaultHostnameVerifier(hv);
    } catch (Exception e) {}
  }
}

72
এটি লক্ষ করা উচিত যে শংসাপত্রের বৈধতা যাচাইকরণ অক্ষম করা সম্ভব এমআইটিএম আক্রমণগুলির সংযোগটি খোলে: উত্পাদনে ব্যবহার করবেন না
ব্রুনো

3
কোড সংকলন করে না, ধন্যবাদ। এই 'সমাধান' মূলত নিরাপত্তাহীন।
মার্নুইস লর্ন

5
@ neu242, না, আপনি এটির জন্য যা ব্যবহার করেন এটি নির্ভর করে না। আপনি যদি এসএসএল / টিএলএস ব্যবহার করতে চান তবে আপনি এমআইটিএম আক্রমণগুলির বিরুদ্ধে আপনার সংযোগটি সুরক্ষিত করতে চান, এটিই পুরো বিষয়টি। সার্ভারের প্রমাণীকরণের প্রয়োজন নেই যদি আপনি গ্যারান্টি দিতে পারেন যে কেউ ট্র্যাফিক পরিবর্তন করতে সক্ষম হবেনা, তবে আপনি যেখানে সন্দেহ করছেন যেগুলি সেখানে শ্রুতিমধুরতা থাকতে পারে যা নেটওয়ার্ক ট্র্যাফিককেও পরিবর্তন করতে পারে না এমন পরিস্থিতিও খুব বিরল।
ব্রুনো

1
@ neu242 কোড স্নিপেটের জন্য ধন্যবাদ। আমি আসলে এটি একটি নির্দিষ্ট নির্দিষ্ট উদ্দেশ্যে (ওয়েব ক্রলিং) উত্পাদনে ব্যবহার করার কথা ভাবছি এবং আমি একটি প্রশ্নে আপনার প্রয়োগের কথা উল্লেখ করেছি (( স্ট্যাকওভারফ্লো / ক্রোয়েশনস / ১১৩০6565৫১১/২ )। আপনার যদি সময় থাকে তবে আপনি কি দয়া করে এটি দেখতে পারেন, এবং যদি আমার কোনও সুরক্ষিত ঝুঁকি মিস হয় তবে তা আমাকে জানান?
সাল

1
@ ব্রুনো যদি আমি কেবল সার্ভারটিকেই পিং করছি তবে এমআইটিএম আক্রমণ দ্বারা এটি কি আমাকে আদৌ প্রভাবিত করবে?
ফুনউন

21

আপনি কি কীস্টোর এবং / অথবা ট্রাস্টস্টোর সিস্টেমের বৈশিষ্ট্য সেট করেছেন?

java -Djavax.net.ssl.keyStore=pathToKeystore -Djavax.net.ssl.keyStorePassword=123456

বা কোড সহ

System.setProperty("javax.net.ssl.keyStore", pathToKeyStore);

Javax.net.ssl.trustStore এর সাথে একই


13

আপনি যদি অ্যাকসিস ফ্রেমওয়ার্কটি ব্যবহার করে কোনও ওয়েব পরিষেবা কল নিয়ে কাজ করছেন তবে এর থেকে আরও সহজ উত্তর পাওয়া যাবে। আপনার ক্লায়েন্ট এসএসএল ওয়েব পরিষেবাতে কল করতে এবং এসএসএল শংসাপত্রের ত্রুটি উপেক্ষা করতে সক্ষম হবার জন্য যদি সমস্তটাই চান তবে আপনি কোনও ওয়েব পরিষেবাদি শুরু করার আগে এই বিবৃতিটি রাখুন:

System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");

এটি একটি উত্পাদন পরিবেশে করার জন্য খুব খারাপ জিনিস হওয়ার বিষয়ে সাধারণ অস্বীকৃতি প্রযোজ্য।

আমি এটি এক্সিস উইকিতে পেয়েছি ।


ওপি অক্ষর নয়, একটি এইচটিপিএসর
URL সংযোগ নিয়ে কাজ করছে

2
আমি বুঝেছি. আমার উত্তরটি সাধারণ ক্ষেত্রে আরও ভাল ছিল তা বোঝানোর আমি ইচ্ছা করি না। এটা ঠিক যে যদি তুমি হয় অক্ষ পরিকাঠামোকে ব্যবহার করে, আপনি যে প্রেক্ষাপটে ওপি প্রশ্ন থাকতে পারে। (এইভাবে আমি এই প্রশ্নটি প্রথম স্থানে খুঁজে পেয়েছি)) সেক্ষেত্রে আমি যেভাবে সরবরাহ করেছি তা সহজ।
মার্ক মিউয়ার

5

আমার জন্য এটি অ্যাপাচি এইচটিপিপি কম্পোনেন্টস using এইচটিটিপি ক্লায়েন্ট 4.x ব্যবহার করে কাজ করেছে:

    KeyStore keyStore  = KeyStore.getInstance("PKCS12");
    FileInputStream instream = new FileInputStream(new File("client-p12-keystore.p12"));
    try {
        keyStore.load(instream, "helloworld".toCharArray());
    } finally {
        instream.close();
    }

    // Trust own CA and all self-signed certs
    SSLContext sslcontext = SSLContexts.custom()
        .loadKeyMaterial(keyStore, "helloworld".toCharArray())
        //.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) //custom trust store
        .build();
    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
        sslcontext,
        new String[] { "TLSv1" },
        null,
        SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); //TODO
    CloseableHttpClient httpclient = HttpClients.custom()
        .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) //TODO
        .setSSLSocketFactory(sslsf)
        .build();
    try {

        HttpGet httpget = new HttpGet("https://localhost:8443/secure/index");

        System.out.println("executing request" + httpget.getRequestLine());

        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }

পি 12 ফাইলটিতে ক্লাসিটি শংসাপত্র এবং ক্লায়েন্টের ব্যক্তিগত কী রয়েছে, যা বোর্সি ক্যাসল দিয়ে নির্মিত হয়েছে:

public static byte[] convertPEMToPKCS12(final String keyFile, final String cerFile,
    final String password)
    throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException,
    NoSuchProviderException
{
    // Get the private key
    FileReader reader = new FileReader(keyFile);

    PEMParser pem = new PEMParser(reader);
    PEMKeyPair pemKeyPair = ((PEMKeyPair)pem.readObject());
    JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter().setProvider("BC");
    KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair);

    PrivateKey key = keyPair.getPrivate();

    pem.close();
    reader.close();

    // Get the certificate
    reader = new FileReader(cerFile);
    pem = new PEMParser(reader);

    X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject();
    java.security.cert.Certificate x509Certificate =
        new JcaX509CertificateConverter().setProvider("BC")
            .getCertificate(certHolder);

    pem.close();
    reader.close();

    // Put them into a PKCS12 keystore and write it to a byte[]
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
    ks.load(null);
    ks.setKeyEntry("key-alias", (Key) key, password.toCharArray(),
        new java.security.cert.Certificate[]{x509Certificate});
    ks.store(bos, password.toCharArray());
    bos.close();
    return bos.toByteArray();
}

keyStoreকি ব্যক্তিগত কী ও সার্টিফিকেট থাকে।
এপিকপান্ডাফোরস

1
রূপান্তরকৃত ইম্টোপি 12 কোডের কাজ করার জন্য আপনাকে এই 2 নির্ভরতা অন্তর্ভুক্ত করতে হবে: <d dependency> <groupId> org.bouncycastle </groupId> <artifactId> bcprov-jdk15on </artifactId> <version> 1.53 </version> </d dependency> নির্ভরতা> <groupId> org.bouncycastle </groupId> <artifactId> bcpkix-jdk15on </artifactId> <version> 1.53 </version> </
d

@ এপিকপান্ডা ফরাস আমি একটি ত্রুটি পেয়েছি: ধরা পড়ে: org.codehaus.groovy.runtime.typehandling.GroovyCastException: 'org.bouncycastle.jcajce.provider.asymmetric.x509.X509 সার্টিফিকেট অবজেক্ট' ক্লাসে 'শ্রেণিতে' 'শ্রেণিতে অবজেক্ট কাস্ট করা যায় না। setKeyEntry - ভুল হতে পারে যে কোনও ক্লু
বিশাল বিয়ানি

হ্যাঁ, আপনি কঠোরভাবে টাইপ করা ভাষার পরিবর্তে গ্রোভি ব্যবহার করছেন। (প্রযুক্তিগতভাবে সেই পদ্ধতিটি কেবল একটি শংসাপত্র নয়, একটি আইডি এবং একটি শংসাপত্র গ্রহণ করে)
EpicPandaForce

4

আমি আমার বর্তমান প্রকল্পে এটি করার জন্য অ্যাপাচি কমন্স এইচটিটিপি ক্লায়েন্ট প্যাকেজটি ব্যবহার করি এবং এটি এসএসএল এবং একটি স্ব-স্বাক্ষরিত সার্টের (আপনার উল্লেখের মতো ক্যাশেয়ারে এটি ইনস্টল করার পরে) দিয়ে কাজ করে। দয়া করে এখানে এটি একবার দেখুন:

http://hc.apache.org/httpclient-3.x/tutorial.html

http://hc.apache.org/httpclient-3.x/sslguide.html


1
এটি দেখতে বেশ ঝরঝরে প্যাকেজ হিসাবে মনে হচ্ছে, তবে যে ক্লাসটি এটির সব কাজ করতে হবে তা 'আথএসএসএলপ্রোটোকলসকেটফ্যাক্টরি' অবশ্যই সরকারীভাবে বিতরণের অংশ নয়, 4.0beta তেও নয় (প্রকাশিত নোটগুলি এটি উল্লেখ করে) বা 3.1-এ নেই। আমি এটির সাথে কিছুটা হ্যাক করেছি এবং সংযোগটি ড্রপ করার আগে এখন 5 মিনিটের সাথে স্থায়ীভাবে আটকা পড়েছে বলে মনে হচ্ছে। এটি সত্যিই অদ্ভুত - যদি আমি কোনও ব্রাউজারে সিএ এবং ক্লায়েন্টের সার্টিটি লোড করি তবে এটি কেবল উড়ে যায়।
জানুয়ারী

1
অ্যাপাচি এইচটিটিপি ক্লায়েন্ট 4 SSLContextসরাসরি নিতে পারে , তাই আপনি ব্যবহারের পরিবর্তে এই সমস্তভাবে কনফিগার করতে পারেন AuthSSLProtocolSocketFactory
ব্রুনো

1
বাহ্যিক কীস্টোরের পরিবর্তে সমস্ত ক্লায়েন্টের শংসাপত্রের স্টাফগুলিকে মেমরি করার কোনও উপায় আছে কি?
শ্রীধর সারনোবাত

4

আমার মনে হয় আপনার সার্ভার শংসাপত্র নিয়ে আপনার সমস্যা আছে, এটি কোনও বৈধ শংসাপত্র নয় (আমি মনে করি এটি "হ্যান্ডশেক_ফিলার" এই ক্ষেত্রে এর অর্থ):

আপনার সার্ভার শংসাপত্রটি ক্লায়েন্টের জেআরই-তে আপনার বিশ্বাসকারীর কীস্টোরগুলিতে আমদানি করুন। কীটোলে এটি সহজেই সম্পন্ন হয় :

keytool
    -import
    -alias <provide_an_alias>
    -file <certificate_file>
    -keystore <your_path_to_jre>/lib/security/cacerts

আমি পরিষ্কার করার চেষ্টা করে ওভার শুরু করেছি এবং হ্যান্ডশেক ব্যর্থতা চলে গেল। সংযোগটি শেষ হওয়ার আগে এখন আমি মাত্র 5 মিনিটের মৃত নীরবতা পেয়েছি: ও
জানুয়ারী

1

নীচে কোড ব্যবহার করা হচ্ছে

-Djavax.net.ssl.keyStoreType=pkcs12

অথবা

System.setProperty("javax.net.ssl.keyStore", pathToKeyStore);

প্রয়োজন হয় না। এছাড়াও আপনার নিজস্ব কাস্টম এসএসএল কারখানা তৈরি করার দরকার নেই।

আমি একই সমস্যার মুখোমুখি হয়েছিলাম, আমার ক্ষেত্রে একটি সমস্যা ছিল যে সম্পূর্ণ শংসাপত্র শৃঙ্খলা ট্রাস্টস্টোরগুলিতে আমদানি করা হয়নি। কীটল ইউটিলিটি ডান ফম রুট শংসাপত্র ব্যবহার করে শংসাপত্রগুলি আমদানি করুন, আপনি নোটপ্যাডে ক্যাসার্টস ফাইলটি খুলতে পারেন এবং দেখুন শংসাপত্রের সম্পূর্ণ শৃঙ্খলা আমদানি করা হয়েছে কি না। শংসাপত্র আমদানি করার সময় আপনি যে উপনামের নামটি দিয়েছিলেন তার বিরুদ্ধে পরীক্ষা করুন, শংসাপত্রগুলি খুলুন এবং দেখুন এটিতে কতটি রয়েছে, একই সংখ্যক শংসাপত্র ক্যাসর্ট ফাইলে থাকা উচিত।

এছাড়াও আপনি যে অ্যাপ্লিকেশনটি চালাচ্ছেন সেই সার্ভারে ক্যাসের্টস ফাইলটি কনফিগার করা উচিত, দুটি সার্ভার সর্বজনীন / ব্যক্তিগত কী দ্বারা একে অপরকে প্রমাণীকরণ করবে।


আপনার নিজস্ব কাস্টম এসএসএল কারখানা তৈরি করা দুটি সিস্টেমের বৈশিষ্ট্য নির্ধারণের চেয়ে অনেক জটিল এবং ত্রুটি-প্রবণ।
লার্নের মারকুইস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.