views:

1037

answers:

6

Im trying to set the certificate friendly name during the certificate request/acceptance process. I understand that this a property of the microsoft store rather than the certificate and an wondering what .net/c# technique might be used to set it.

+1  A: 

So here is a commmand line example of how to do this. You need CAPICOM from microsoft which wraps the CryptoAPI.

The friendly name is a property of the cert store rather than the certificate so this code imports a certificate to the cert store and sets the friendly name as it does so.

The code takes two parameters the path to the cert file and the friendly name you wish to set.

Code:-

using System;

using System.Collections.Generic;

using System.Text;

using CAPICOM;

using System.Collections;

using System.Runtime.InteropServices;


namespace CertTool

{

    class Program
    {
        const uint CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x20000;
        const int CAPICOM_PROPID_FRIENDLY_NAME = 11;
        const int CAPICOM_ENCODE_BINARY = 1;

        static private String _currStoreName = "My";
        static private String _FriendlyName = "Not Set";
        static private String _CertPath = "C:\\test.cer";
        static StoreClass _oCurrStore;
        static ExtendedPropertyClass _friendlyProp;
        static CertificateClass _certificate;
        static ExtendedProperties _extendedProp;

        static void Main(string[] args)
        {
            try
            {
                //Friendly name Argument
                if (args.Length > 0)
                {
                    _FriendlyName = args[0];
                }
                //Certpath argument
                if (args.Length > 1) 
                {
                    _CertPath = args[1];
                }
                //Set and open the Store
                _oCurrStore = new StoreClass();
                _oCurrStore.Open(
                    CAPICOM_STORE_LOCATION.CAPICOM_LOCAL_MACHINE_STORE,
                    _currStoreName,
                    CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_EXISTING_ONLY |
                    CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);
                //Call the import certificate function
                importCert();
            }
            catch(Exception ex){
                Console.WriteLine(ex.Message);
                Console.WriteLine(args[0]);
            }
        }
        //Function import the certificate to the machine store and sets the friendly name
        static bool importCert()
        {
            try
            {
                //Create Certificate Object
                _certificate = new CertificateClass();
                //Load the certificate into the obejct from file
                _certificate.Load(_CertPath, "", CAPICOM_KEY_STORAGE_FLAG.CAPICOM_KEY_STORAGE_EXPORTABLE, CAPICOM_KEY_LOCATION.CAPICOM_LOCAL_MACHINE_KEY);
                //Create extended property Class for friendly name
                _friendlyProp = new ExtendedPropertyClass();
                _friendlyProp.PropID =  CAPICOM_PROPID.CAPICOM_PROPID_FRIENDLY_NAME;
                _friendlyProp.set_Value(CAPICOM_ENCODING_TYPE.CAPICOM_ENCODE_BINARY, _FriendlyName);

                //Add extendedProp on cert object
                _extendedProp = _certificate.ExtendedProperties();
                //Set extendded prop to friendly name object
                _extendedProp.Add(_friendlyProp);
                _oCurrStore.Add(_certificate);
                return true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(_CertPath);
                return true;
            }
        }
    }
}

Regards
Mark Sutton
http://www.blacktipconsulting.com

Mark Sutton
+1  A: 

Really friendlyName is not a cert store properties but a PKCS#12 attribute to add to a X509 certificate. PKCS#12 is a standard for personal data exchange and it used to packs X509 certificate and the related private key. A friendlyName is an attribute added to the final PKCS#12 file define in this standard.

To generare X509Certificate in PKCS#12 format you can try the X509Builder web application at http://www.we-coffee.com/x509builder.aspx

Matteo Slaviero
A: 

the codes using CAPICOM works perfectly!

Ning
A: 

I get this error when executing : _oCurrStore = new StoreClass();

Retrieving the COM class factory for component with CLSID {91D221C4-0CD4-461C-A728-01D509321556} failed due to the following error: 80040154.

My PC is runnning Win7.

AnHund
A: 

Ok, found an answer to that here:

Hi,

Please have a look at this to check if it suits your need:

When you run the .net Code in X64 Environment you will get the following error message.

" Failed --Retrieving the COM class factory for component with CLSID ...."

E.g. in CMS Export / Import server side .net code = "ExportSiteContentIncremental(...) Failed --Retrieving the COM class factory for component with CLSID {CA0752B3-021C-4F99-82E3-2C0F19C5E953} failed due to the following error: 80040154."

WORKAROUND:

The possible workaround is modify your project's platform from 'Any CPU' to 'X86' (in Project's Properties, Build/Platform's Target)

ROOTCAUSE

The VSS Interop is a managed assembly using 32-bit Framework and the dll contains a 32-bit COM object. If you run this COM dll in 64 bit environment, you will get the error message.

AnHund
A: 

Use X509Certificate2.FriendlyName. However, you must export the certificate as PFX/PKCS#12:

X509Certificate2 certificate = new X509Certificate2(...);
certificate.FriendlyName = "MyName";
File.WriteAllBytes(path, certificate.Export(X509ContentType.Pkcs12));
Steven