简体   繁体   中英

Using creating self-signed certificate in WCF

Hello I have a wcf service that using self-signed certificate. Previous version doesn't have security and i implement it only in new one. But i need to update old versions of programs. That why i need to create certificate in code and add to store. I use code from 1 answer How to create a self-signed certificate using C#? example whith minor changes

public class CertificateTools
{
    public static X509Certificate2 CreateSelfSignedCertificate(string subjectName)
    {
        // create DN for subject and issuer
        var dn = new CX500DistinguishedName();
        dn.Encode("CN=" + subjectName, X500NameFlags.XCN_CERT_NAME_STR_NONE);

        // create a new private key for the certificate
        CX509PrivateKey privateKey = new CX509PrivateKey();
        privateKey.KeyProtection = X509PrivateKeyProtection.XCN_NCRYPT_UI_NO_PROTECTION_FLAG;
        privateKey.ProviderName = "Microsoft Base Cryptographic Provider v1.0";
        privateKey.MachineContext = true;
        privateKey.Length = 1024;
        privateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE; // use is not limited
        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, "SHA1");

        // add extended key usage if you want - look at MSDN for a list of possible OIDs
        var oid = new CObjectId();
        oid.InitializeFromValue("1.3.6.1.5.5.7.3.1"); // SSL server
        var oidlist = new CObjectIds();
        oidlist.Add(oid);
        var eku = new CX509ExtensionEnhancedKeyUsage();
        eku.InitializeEncode(oidlist);


        //KeyUseg
        CX509ExtensionKeyUsage extensionKeyUsage = new CX509ExtensionKeyUsage();
        // Key Usage Extension 
        extensionKeyUsage.InitializeEncode(
            X509KeyUsageFlags.XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE |
            X509KeyUsageFlags.XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE |
            X509KeyUsageFlags.XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE
        );


        // 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.AddYears(-1);
        // this cert expires immediately. Change to whatever makes sense for you
        cert.NotAfter = DateTime.Now.AddYears(100);
        cert.X509Extensions.Add((CX509Extension) extensionKeyUsage);//add the KU
        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 X509Certificate2(Convert.FromBase64String(base64encoded), "",X509KeyStorageFlags.Exportable);
    }
}

and code

        X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadWrite | OpenFlags.IncludeArchived);
        var certificate = CertificateTools.CreateSelfSignedCertificate("ServerAdminService");     
        store.Add(certificate);           
        store.Close();

Usage code

         scb = new ServiceCredentials();
         scb.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "ServerAdminService");

This creates certificate and add it, but when i'm trying to use it error occurred. In the error is said that there is no private key or process does not have permission. It looks like i need to change some flags but i don't know which.

Not seeing the certificate added to the store. See if this helps,

store.Open(OpenFlags.ReadWrite | OpenFlags.IncludeArchived);
    var certificate = CertificateTools.CreateSelfSignedCertificate("ServerAdminService");   
    store.Add(certificate ) ;            
    store.Close();

This is WAY late, but I think the problem is you aren't persisting the private key. In the last line of the cert creation

return new X509Certificate2(Convert.FromBase64String(base64encoded), "",X509KeyStorageFlags.Exportable);

you aren't setting the "X509KeyStorageFlags.PersistKeySet". This causes the private key to be persisted in the new Certificate that you are creating. Otherwise...the certificate gets installed without the private key.

Try:

return new X509Certificate2(Convert.FromBase64String(base64encoded), "",X509KeyStorageFlags.Exportable |  X509KeyStorageFlags.PersistKeySet);

I haven't run it...so no guarantee.

This is also true of adding a X509Certificate2 from a file into a store. When you construct the X509Certificate2 you have to pass the X509KeyStorageFlags.PersistKeySet flag to get it to keep the private key. I know this (loading from file) for sure as I spent many hours troubleshooting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM