How to generate certificate from reqest

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

How to generate certificate from reqest

ziggi slaw
  Scenario: 
- .NET Framework, C#, https://www.pkcs11interop.net/ for communication with HSM, 
- two machines, each with their own HSM,
- machine2 generates pkcs10 CSR with a lot of custom extensions (signed with private key in HSM2) and sends it to Machine1 in byte array format,
- machine1 generates a certificate from the request and signs it with its own private key in HSM1.

I know how to generate CSR, but would need help with generating the certificate.

Code to generate CSR on machine2:
        /// <param name="session">Pkcs11Interop object for communicating with HSM, I'm already logged in a slot</param>
        /// <param name="distinguishedName"></param>
        /// <param name="privateKeyObjectHandle">HSM's private key object handle</param>
        /// <param name="publicKeyObjectHandle">HSM's public key object handle</param>
        /// <param name="attributes">Custom extensions (or attributes?), like KeyUsage, PrivateKeyUsagePeriod, ...</param>
        /// <returns>CSR in byte array format</returns>
        public byte[] GenerateCSR(ISession session, string distinguishedName, ulong privateKeyObjectHandle, ulong publicKeyObjectHandle, DerSet attributes)
        {
            // We need publicKeyParameters for CSR.
            var publicKeyReadAttributes = new List<CKA>
            {
                CKA.CKA_KEY_TYPE,
                CKA.CKA_MODULUS,
                CKA.CKA_PUBLIC_EXPONENT
            };
            var publicKeyAttributesFromHsm = session.GetAttributeValue(
                session.Factories.ObjectHandleFactory.Create(publicKeyObjectHandle),
                publicKeyReadAttributes
            );
            if (CKK.CKK_RSA != (CKK)publicKeyAttributesFromHsm[0].GetValueAsUlong())
            {
                throw new NotSupportedException("InvalidProtocolType");
            }
            var modulusHSM = new BigInteger(1, publicKeyAttributesFromHsm[1].GetValueAsByteArray());
            var publicExponentHSM = new BigInteger(1, publicKeyAttributesFromHsm[2].GetValueAsByteArray());
            var publicKeyParameters = new RsaKeyParameters(false, modulusHSM, publicExponentHSM);

            // PKCS10.
            var name = new X509Name(distinguishedName);
            var pkcs10 = new Pkcs10CertificationRequestDelaySigned(
                PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id,
                name,
                publicKeyParameters,
                attributes
            );
            var signature = session.Sign(
                session.Factories.MechanismFactory.Create(CKM.CKM_SHA256_RSA_PKCS),
                session.Factories.ObjectHandleFactory.Create(privateKeyObjectHandle),
                pkcs10.GetDataToSign()
            );
            pkcs10.SignRequest(new DerBitString(signature));
            var request = pkcs10.GetDerEncoded();
            return request;
        }


This is the interface for generating the certificate on the machine1 (key handles are of course different then in previous method because this code is running on machine1 which has its own HSM):
        public void GenerateCertificateFromRequest(ISession session, ulong privateKeyObjectHandle, ulong publicKeyObjectHandle, byte[] pkcs10)
        {
            // ....
        }


Currently I am trying with X509V3CertificateGenerator, but am not sure if it is the correct way to go... Any help would be much appreciated, thanks!