2017-07-13 13 views
7

लक्ष्य एक ऐसा वेब एप्लिकेशन है जो उपयोगकर्ता के पीसी पर स्थापित C# एप्लिकेशन के साथ जानकारी का आदान-प्रदान करता है। क्लाइंट एप्लिकेशन वेबसाईट सर्वर है और ब्राउज़र वेबसाईट क्लाइंट है।वेबसॉकेट सुरक्षित कनेक्शन स्वयं हस्ताक्षरित प्रमाणपत्र

अंत में उपयोगकर्ता के ब्राउज़र में वेबसाईट क्लाइंट कोणीय के माध्यम से लगातार बनाया जाता है और एप्लिकेशन पीसी पर चल रहा है और कुछ चीजें कर रहा है।

सी # लाइब्रेरी का उपयोग WebSocket-Sharp है। Websocket क्लाइंट सामान्य जावास्क्रिप्ट है।

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

कनेक्शन काम नहीं करता है क्योंकि प्रमाणपत्र अविश्वसनीय है। क्लाइंट के लिए सभी सर्वर चेक अक्षम हैं लेकिन कनेक्शन स्थापित नहीं होगा।

इस भाग सर्वर

_server = new WebSocketServer($"wss://localhost:4649") 
{ 
    SslConfiguration = 
    { 
     ServerCertificate = Utils.Certificate.CreateSelfSignedCert(), 
     ClientCertificateRequired = false, 
     CheckCertificateRevocation = false, 
     ClientCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true 
    } 
}; 
_server.AddWebSocketService<CommandsBehaviour>("/commands"); 
_server.AddWebSocketService<NotificationsBehaviour>("/notifications"); 

_server.Start(); 

बनाई गई है जहां इस तरह के प्रमाण पत्र BouncyCastle

private static AsymmetricKeyParameter CreatePrivateKey(string subjectName = "CN=root") 
{ 
    const int keyStrength = 2048; 

    // Generating Random Numbers 
    var randomGenerator = new CryptoApiRandomGenerator(); 
    var random = new SecureRandom(randomGenerator); 

    // The Certificate Generator 
    var certificateGenerator = new X509V3CertificateGenerator(); 

    // Serial Number 
    var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random); 
    certificateGenerator.SetSerialNumber(serialNumber); 

    // Issuer and Subject Name 
    var subjectDn = new X509Name(subjectName); 
    var issuerDn = subjectDn; 
    certificateGenerator.SetIssuerDN(issuerDn); 
    certificateGenerator.SetSubjectDN(subjectDn); 

    // Valid For 
    var notBefore = DateTime.UtcNow.Date; 
    var notAfter = notBefore.AddYears(70); 

    certificateGenerator.SetNotBefore(notBefore); 
    certificateGenerator.SetNotAfter(notAfter); 

    // Subject Public Key 
    var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); 
    var keyPairGenerator = new RsaKeyPairGenerator(); 
    keyPairGenerator.Init(keyGenerationParameters); 
    var subjectKeyPair = keyPairGenerator.GenerateKeyPair(); 

    return subjectKeyPair.Private; 
} 

public static X509Certificate2 CreateSelfSignedCert(string subjectName = "CN=localhost", string issuerName = "CN=root") 
{ 
    const int keyStrength = 2048; 
    var issuerPrivKey = CreatePrivateKey(); 

    // Generating Random Numbers 
    var randomGenerator = new CryptoApiRandomGenerator(); 
    var random = new SecureRandom(randomGenerator); 
    ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerPrivKey, random); 
    // The Certificate Generator 
    var certificateGenerator = new X509V3CertificateGenerator(); 
    certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(new GeneralName[] { new GeneralName(GeneralName.DnsName, "localhost"), new GeneralName(GeneralName.DnsName, "127.0.0.1") })); 
    certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage((new ArrayList() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1") }))); 

    // Serial Number 
    var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); 
    certificateGenerator.SetSerialNumber(serialNumber); 

    // Signature Algorithm 
    //const string signatureAlgorithm = "SHA512WITHRSA"; 
    //certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm); 

    // Issuer and Subject Name 
    var subjectDn = new X509Name(subjectName); 
    var issuerDn = new X509Name(issuerName); 
    certificateGenerator.SetIssuerDN(issuerDn); 
    certificateGenerator.SetSubjectDN(subjectDn); 

    // Valid For 
    var notBefore = DateTime.UtcNow.Date; 
    var notAfter = notBefore.AddYears(70); 

    certificateGenerator.SetNotBefore(notBefore); 
    certificateGenerator.SetNotAfter(notAfter); 

    // Subject Public Key 
    var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); 
    var keyPairGenerator = new RsaKeyPairGenerator(); 
    keyPairGenerator.Init(keyGenerationParameters); 
    var subjectKeyPair = keyPairGenerator.GenerateKeyPair(); 

    certificateGenerator.SetPublicKey(subjectKeyPair.Public); 

    // self sign certificate 
    var certificate = certificateGenerator.Generate(signatureFactory); 

    // corresponding private key 
    var info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private); 


    // merge into X509Certificate2 
    var x509 = new X509Certificate2(certificate.GetEncoded()); 

    var seq = (Asn1Sequence)Asn1Object.FromByteArray(info.ParsePrivateKey().GetDerEncoded()); 
    if (seq.Count != 9) 
    { 
     throw new PemException("malformed sequence in RSA private key"); 
    } 

    var rsa = RsaPrivateKeyStructure.GetInstance(seq); //new RsaPrivateKeyStructure(seq); 
    var rsaparams = new RsaPrivateCrtKeyParameters(
     rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient); 

    x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams); 
    return x509; 

} 

यह व्यवहार तार्किक है, हालांकि यह प्रमाणपत्र की जांच shouldn 'के रूप में अजीब बात है के साथ बनाया जाता है है टी स्थानीय रूप से प्रदर्शन किया जाना चाहिए। क्या इस समस्या को बाईपास करने की संभावना है? मैंने पहले से ही विश्वसनीय कर्ट को जारीकर्ता प्रमाण पत्र स्थापित करने के बारे में सोचा है लेकिन यह एक इष्टतम समाधान नहीं है।

+2

'प्रमाण पत्र स्थानीय रूप से नहीं किया जाना चाहिए' हू? – SLaks

+0

@SLaks मेरा मतलब है कि जब कनेक्शन स्थानीयहोस्ट – chris579

उत्तर

4

क्या आपने इस question पर दिए गए किसी भी उत्तर का प्रयास किया है?

संक्षेप में, यह लग रहा है उसके लिए कुछ विकल्प आप की कोशिश कर सकते हैं जैसे: --ignore-certificate-errors तर्क निर्दिष्ट साथ

  • प्रारंभ क्रोम।

  • उसी पोर्ट पर एक HTTP सर्वर प्रारंभ करें जो एक ही स्व-हस्ताक्षरित प्रमाणपत्र लेता है, उसे ब्राउज़ करता है, और प्रमाणपत्र स्वीकार करता है, जिसके बाद आप वेबसॉकेट कनेक्शन का उपयोग करने में सक्षम होना चाहिए।

  • सेट true करने के लिए Firefox network.websocket.allowInsecureFromHTTPS पर विन्यास विकल्प है, तो ws:// बजाय wss:// पते का उपयोग करें।

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

+0

के साथ कनेक्शन किया जाता है तो प्रमाण को मजबूर नहीं किया जाना चाहिए क्या आपके पास इस समस्या के वैकल्पिक समाधान के लिए कोई सुझाव है? मैंने वेबआरटीसी के बारे में सोचा लेकिन सी # के लिए कोई अच्छा कार्यान्वयन नहीं है। क्या ऐसे अन्य विकल्प हैं जो इस तरह की संरचना की अनुमति दे सकते हैं: http://img.klemm.one/EZRYx? एक समाधान सर्वर और क्लाइंट को स्वैप कर सकता है ताकि ब्राउजर सर्वर हो। लेकिन मुझे यकीन नहीं है कि यह संभव है या नहीं। – chris579

+0

मैं इस सामान में एक विशेषज्ञ नहीं हूं, लेकिन मुझे लगता है कि आपने @ फैबियन के जवाब को बहुत जल्दी खारिज कर दिया होगा। चूंकि Let's Encrypt एक विश्वसनीय CA (https://letsencrypt.org/2015/10/19/lets-encrypt-is-trusted.html) है, तो आपको विश्वसनीय certs में प्रमाणपत्र जोड़ने की आवश्यकता नहीं होगी, क्योंकि यह पहले से ही है पर भरोसा किया। मुझे लगता है कि आपको कुछ भी अतिरिक्त किए बिना https/wss का उपयोग करने में सक्षम होना चाहिए। – Kdawg

+0

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

4

@Kdawg उत्तर सही हैं।

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

  1. एक विंडोज सर्वर निरुपित प्रमाणपत्र प्राधिकारी के रूप में

  2. कार्य करने के लिए:

    मैं @ Kdawg के जवाब के शीर्ष पर, जोड़ने के लिए Windows नेटवर्क पर, निजी संगठनों के लिए सबसे आम अभ्यास करने के लिए है कि चाहते हैं

  3. विंडोज मेजबान में प्रमाणपत्र प्राधिकारी के सार्वजनिक रूट प्रमाणपत्र जोड़ें (या तो GPO द्वारा) या manually

  4. साइन विंडोज के साथ विशेष रूप से निर्मित प्रमाण पत्र सीए सर्वर

यह दर्दनाक लगता है, और यह है।

यदि मैं आप थे, तो मैं एक मानक सार्वजनिक रूप से हस्ताक्षरित प्रमाणपत्र बनाने के लिए जाऊंगा और इसे पूरा होने तक एसएसएल चलाएगा।

अपने डोमेन के लिए मुफ्त SSL प्रमाणपत्रों के लिए Let's Encrypt पर देखें।

+0

समस्या स्वयं डोमेन के लिए अनुपलब्ध एसएसएल प्रमाण नहीं है बल्कि यह संचार की संरचना है जिसे हासिल किया जाना चाहिए। यह इस प्रकार होना चाहिए: http://img.klemm.one/EZRYx। एसएसएल बंद करना एक विकल्प नहीं है और भरोसेमंद certs में प्रमाणपत्र जोड़ना एक विकल्प भी नहीं है। क्या वेबसाइकिलों के विकल्प हैं जिनका उपयोग इस के लिए किया जा सकता है? मैंने कच्चे टीसीपी का उपयोग करने के बारे में सोचा लेकिन क्लाइंट साइड जावास्क्रिप्ट इस में सक्षम नहीं है। – chris579

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