Convert Pkcs11X509Certificate to X509Certificate2 to use as ssl client cert

187 Views Asked by At

I am quite new to this... I have safenet luna hsm storing certs. I need to retrieve cert and use it as client cert in an ssl session. I am trying to use Pkcs11Interop (and also Pkcs11X509Store) without success. I cant get the X509Certificate2 with the private key. here is what I have so far : with Pkcs11X509Store:

using (var store = new Pkcs11X509Store(@"c:\program files\Safenet\Lunaclient\cryptoki.dll", new ConstPinProvider(ConfigurationManager.AppSettings["pin"])))
        {
            Pkcs11X509Certificate cert = store.Slots[0].Token.Certificates.FirstOrDefault(p => p.Info.ParsedCertificate.SerialNumber.ToLower() == ConfigurationManager.AppSettings["certsn"].ToLower());
            //RSA rsaPrivateKey = cert.GetRSAPrivateKey();
            X509Certificate2 x509cert = cert.Info.ParsedCertificate;
            // here cert.HasPrivateKeyObject is true but x509cert.HasPrivateKey is false
        }

so x509cert is not working as valid cert for ssl...

with Pkcs11Interop :

using (IPkcs11Library pkcs11Library = Settings.Factories.Pkcs11LibraryFactory.LoadPkcs11Library(Settings.Factories, Settings.Pkcs11LibraryPath, Settings.AppType))
            {
                ISlot slot = Helpers.GetUsableSlot(pkcs11Library);
                using (ISession session = slot.OpenSession(SessionType.ReadOnly))
                {
                    session.Login(CKU.CKU_USER, Settings.NormalUserPin);
                    List<IObjectAttribute> objectAttributes = new List<IObjectAttribute>();
                    objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_CERTIFICATE));
                    session.FindObjectsInit(objectAttributes);
                    X509Certificate2 x509cert  = new X509Certificate2();
                    List<IObjectHandle> foundObjects = session.FindAllObjects(objectAttributes);
                    string cka_id = "";
                    foreach (IObjectHandle foundObjectHandle in foundObjects)
                    {
                        List<IObjectAttribute> certAttributes = session.GetAttributeValue(foundObjectHandle, new List<CKA>() { CKA.CKA_VALUE, CKA.CKA_ID });
                        X509Certificate2 x509Cert2 = new X509Certificate2(certAttributes[0].GetValueAsByteArray());
                        if (x509Cert2.SerialNumber.ToLower() == ConfigurationManager.AppSettings["certsn"].ToLower())
                        {
                            cka_id = certAttributes[1].GetValueAsString();
                            x509cert  = x509Cert2;
                            break;
                        }
                    }
                    objectAttributes.Clear();
                    objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
                    foundObjects.Clear();
                    foundObjects = session.FindAllObjects(objectAttributes);
                    foreach (IObjectHandle foundObjectHandle in foundObjects)
                    {
                        List<IObjectAttribute> keyAttributes = session.GetAttributeValue(foundObjectHandle, new List<CKA>() { CKA.CKA_VALUE, CKA.CKA_ID });
                        if (cka_id == keyAttributes[1].GetValueAsString())
                        {
                            //how to assign private key to x509cert  ?
                            break;
                        }
                    }
                    session.FindObjectsFinal();

            

Is there a way to get a X509Certificate2 which can be used later as ssl client cert ?

Thanks in advance for any help.

/JS

1

There are 1 best solutions below

2
jariq On

Instances of X509Certificate2 classes returned by Pkcs11Interop.Store library cannot be used in SSL connections. That's a known limitation caused by limited extensibility of X509Certificate2 class. If you want to use X509Certificate2 object with SSL connections then you need to get it from standard X509Store.