मेरे पास एक स्व-होस्टेड डब्ल्यूसीएफ सर्वर है जो स्थानीय सिस्टम खाते के तहत विंडोज सेवा के रूप में चल रहा है। मैं संदेश स्तर सुरक्षा का उपयोग कर नेट.tcp एंडपॉइंट के साथ उपयोग के लिए सी # में प्रोग्रामेटिक रूप से एक स्व-हस्ताक्षरित प्रमाणपत्र बनाने की कोशिश कर रहा हूं।डब्ल्यूसीएफ सेवा के लिए प्रोग्रामेटिक रूप से स्व-हस्ताक्षरित प्रमाणपत्र कैसे बनाएं?
मैं निम्नलिखित कोड का उपयोग कर रहा हूं जो How to create a self-signed certificate using C#? में स्वीकृत उत्तर के आधार पर मेरी समस्या को हल करने की कोशिश कर रहे कुछ छोटे बदलावों के साथ बहुत करीब से है।
public static X509Certificate2 CreateSelfSignedCertificate(string subjectName, TimeSpan expirationLength)
{
// create DN for subject and issuer
var dn = new CX500DistinguishedName();
dn.Encode("CN=" + subjectName, X500NameFlags.XCN_CERT_NAME_STR_NONE);
CX509PrivateKey privateKey = new CX509PrivateKey();
privateKey.ProviderName = "Microsoft Strong Cryptographic Provider";
privateKey.Length = 1024;
privateKey.KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE;
privateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_DECRYPT_FLAG | X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_KEY_AGREEMENT_FLAG;
privateKey.MachineContext = true;
privateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_FLAG;
privateKey.Create();
// Use the stronger SHA512 hashing algorithm
var hashobj = new CObjectId();
hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY,
AlgorithmFlags.AlgorithmFlagsNone, "SHA1");
// Create the self signing request
var cert = new CX509CertificateRequestCertificate();
cert.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextMachine, privateKey, "");
cert.Subject = dn;
cert.Issuer = dn; // the issuer and the subject are the same
cert.NotBefore = DateTime.Now.Date;
// this cert expires immediately. Change to whatever makes sense for you
cert.NotAfter = cert.NotBefore + expirationLength;
//cert.X509Extensions.Add((CX509Extension)eku); // add the EKU
cert.HashAlgorithm = hashobj; // Specify the hashing algorithm
cert.Encode(); // encode the certificate
// Do the final enrollment process
var enroll = new CX509Enrollment();
enroll.InitializeFromRequest(cert); // load the certificate
enroll.CertificateFriendlyName = subjectName; // Optional: add a friendly name
string csr = enroll.CreateRequest(); // Output the request in base64
// and install it back as the response
enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate,
csr, EncodingType.XCN_CRYPT_STRING_BASE64, ""); // no password
// output a base64 encoded PKCS#12 so we can import it back to the .Net security classes
var base64encoded = enroll.CreatePFX("", // no password, this is for internal consumption
PFXExportOptions.PFXExportChainWithRoot);
// instantiate the target class with the PKCS#12 data (and the empty password)
return new System.Security.Cryptography.X509Certificates.X509Certificate2(
System.Convert.FromBase64String(base64encoded), "",
// mark the private key as exportable (this is usually what you want to do)
// mark private key to go into the Machine store instead of the current users store
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet
);
}
और मैं यह इस कोड के साथ की दुकान:
X509Store store = new X509Store(storeName, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(newCert);
store.Close();
यह प्रमाणपत्र बनाता है और LocalMachine प्रमाणपत्र संग्रह में कहते हैं। समस्या यह है कि जब मैं डब्ल्यूसीएफ सेवा शुरू करने का प्रयास करता हूं तो मुझे निम्नलिखित अपवाद मिलता है:
यह संभावना है कि प्रमाणपत्र 'सीएन = myCertificate' में एक निजी कुंजी नहीं हो सकती है जो कुंजी विनिमय करने में सक्षम हो या प्रक्रिया हो निजी कुंजी के लिए अधिकारों का उपयोग। विस्तार के लिए कृपया आंतरिक अपवाद देखें। इनर अपवाद: कुंजी समुच्चय
मौजूद नहीं है मेरी प्रमाण पत्र के लिए FindPrivateKey नमूना (http://msdn.microsoft.com/en-us/library/aa717039%28v=vs.100%29.aspx) के उत्पादन में है:
Private key directory:
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
Private key file name:
f0d47c7826b8ef5148b6d412f1c40024_4a8a026f-58e4-40f7-b779-3ae9b6aae1a7
मैं एक्सप्लोरर में इस 1.43KB फ़ाइल देख सकते हैं। अगर मैं गुणों को देखता हूं। सुरक्षा मैं पूर्ण नियंत्रण के साथ सिस्टम और प्रशासक दोनों को देखता हूं।
इस त्रुटि की खोज में मैंने निजी कुंजी गायब या गलत अनुमतियों के बारे में कई उत्तरों को देखा है। मैं नहीं देख सकता कि समस्या क्या है।
वास्तव में अजीब बात यह है कि अगर मैं एमएमसी प्रमाणपत्र प्लगइन का उपयोग करता हूं, तो प्रमाण पत्र पर जाएं और सभी कार्य चुनें। निजी कुंजी प्रबंधित करें ... मुझे वही सुरक्षा सेटिंग्स दिखाई देती हैं। इसे देखने के बाद भी अगर मैं सिर्फ संवाद लाता हूं और रद्द करें बटन दबाता हूं तो प्रमाण पत्र अब डब्ल्यूसीएफ में सही तरीके से काम करता है। मैं बस सेवा को पुनरारंभ कर सकता हूं और सबकुछ पूरी तरह से चलता है।
यदि मैं मेकर्ट का उपयोग करके प्रमाण पत्र बनाता हूं तो यह शुरुआत से ठीक काम करता है। मुझे नहीं पता कि यह अलग-अलग क्या करता है।
जानकारी का एक अन्य टुकड़ा प्रासंगिक नहीं हो सकता है कि प्रमाण पत्र न केवल मेरे स्टोर में रखा जाता है जहां मैंने इसे रखने के लिए कहा था, लेकिन इसे "इंटरमीडिएट सर्टिफिकेशन अथॉरिटीज" स्टोर में भी रखा जाता है। मुझे नहीं पता क्यों या क्यों मायने रखता है।
तो ... कोई विचार क्या मैं गलत कर रहा हूं?
अद्यतन: ठीक है, यह सिर्फ एक डब्ल्यूसीएफ मुद्दा नहीं है। जब मैं HttpSetServiceConfiguration का उपयोग कर http.sys के साथ एंडपॉइंट पर बाध्य करने के लिए प्रमाणपत्र का उपयोग करने का प्रयास करता हूं तो मुझे अनिवार्य रूप से वही समस्या मिलती है। विधि 1312 लौटाती है - "एक निर्दिष्ट लॉगऑन सत्र मौजूद नहीं है। इसे पहले ही समाप्त कर दिया जा सकता है"। यह वास्तव में असली त्रुटि नहीं है। मैं सुरक्षा इवेंट में देखा था लॉग इन करें एक लेखापरीक्षा विफलता है कि इस कहते हैं:
Cryptographic Parameters:
Provider Name: Microsoft Software Key Storage Provider
Algorithm Name: Not Available.
Key Name: {A23712D0-9A7B-4377-89DB-B1B39E3DA8B5}
Key Type: Machine key.
Cryptographic Operation:
Operation: Open Key.
Return Code: 0x80090011
0x80090011 वस्तु नहीं मिला था है। तो यह एक ही समस्या प्रतीत होता है। फिर, प्रमाणपत्र के लिए निजी कुंजी प्रबंधित करें संवाद खोलने के बाद यह पूरी तरह से काम करता है।
मैं अभी भी समस्या का कारण ढूंढ रहा हूं।
अद्यतन # 2: मैं नीचे दिए गए स्वीकृत उत्तर का उपयोग करके यह काम करने में सक्षम था। दिलचस्प बात यह है कि अब यह कोड X509Store कोड को कॉल किए बिना मशीन स्टोर में प्रमाण पत्र डालता प्रतीत होता है। मैं अभी भी कोड को कॉल करता हूं क्योंकि मुझे यकीन नहीं है और इससे कुछ भी नुकसान नहीं पहुंचाता है। यहां अंतिम कोड है जिसका उपयोग मैं प्रमाण पत्र बनाने के लिए कर रहा हूं।
static public X509Certificate2 CreateSelfSignedCertificate(string subjectName, TimeSpan expirationLength)
{
// create DN for subject and issuer
var dn = new CX500DistinguishedName();
dn.Encode("CN=" + subjectName, X500NameFlags.XCN_CERT_NAME_STR_NONE);
CX509PrivateKey privateKey = new CX509PrivateKey();
privateKey.ProviderName = "Microsoft Strong Cryptographic Provider";
privateKey.Length = 2048;
privateKey.KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE;
privateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_DECRYPT_FLAG | X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_KEY_AGREEMENT_FLAG;
privateKey.MachineContext = true;
privateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
privateKey.Create();
// Use the stronger SHA512 hashing algorithm
var hashobj = new CObjectId();
hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY,
AlgorithmFlags.AlgorithmFlagsNone, "SHA512");
// Create the self signing request
var cert = new CX509CertificateRequestCertificate();
cert.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextMachine, privateKey, "");
cert.Subject = dn;
cert.Issuer = dn; // the issuer and the subject are the same
cert.NotBefore = DateTime.Now.Date;
// this cert expires immediately. Change to whatever makes sense for you
cert.NotAfter = cert.NotBefore + expirationLength;
cert.HashAlgorithm = hashobj; // Specify the hashing algorithm
cert.Encode(); // encode the certificate
// Do the final enrollment process
var enroll = new CX509Enrollment();
enroll.InitializeFromRequest(cert); // load the certificate
enroll.CertificateFriendlyName = subjectName; // Optional: add a friendly name
string csr = enroll.CreateRequest(); // Output the request in base64
// and install it back as the response
enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate,
csr, EncodingType.XCN_CRYPT_STRING_BASE64, ""); // no password
// output a base64 encoded PKCS#12 so we can import it back to the .Net security classes
var base64encoded = enroll.CreatePFX("", // no password, this is for internal consumption
PFXExportOptions.PFXExportChainWithRoot);
// instantiate the target class with the PKCS#12 data (and the empty password)
return new System.Security.Cryptography.X509Certificates.X509Certificate2(
System.Convert.FromBase64String(base64encoded), "",
// mark the private key as exportable (this is usually what you want to do)
// mark private key to go into the Machine store instead of the current users store
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet
);
}
क्या कोई जानता है कि किसी मौजूदा प्रमाणपत्र को दोस्ताना नाम से कैसे लोड किया जाए? –
अद्यतन प्रदान करने के लिए धन्यवाद .. मेरे पास एक समान समस्या थी और मैं यह गलत नहीं कर सका कि मैं क्या कर रहा था, आपने इस पोस्ट के साथ मुझे बहुत मदद की! :) – Spyral