private static byte[] EncodeData(byte[] publicKey, byte[] serialNumber) { IntPtr publicKeyPtr = IntPtr.Zero, serialNumberPtr = IntPtr.Zero; try { var identifier = new CERT_AUTHORITY_KEY_ID2_INFO(); identifier.AuthorityCertIssuer = new CERT_ALT_NAME_INFO { cAltEntry = 0 }; if (serialNumber != null) { serialNumberPtr = Marshal.AllocHGlobal(serialNumber.Length); Marshal.Copy(serialNumber, 0, serialNumberPtr, serialNumber.Length); identifier.AuthorityCertSerialNumber = new CRYPTOAPI_BLOB { cbData = (uint)serialNumber.Length, pbData = serialNumberPtr }; } if (publicKey != null) { publicKeyPtr = Marshal.AllocHGlobal(publicKey.Length); Marshal.Copy(publicKey, 0, publicKeyPtr, publicKey.Length); identifier.KeyId = new CRYPTOAPI_BLOB { cbData = (uint)publicKey.Length, pbData = publicKeyPtr }; } uint dataSize = 0; LocalBufferSafeHandle data; if (!Crypt32.CryptEncodeObjectEx(EncodingType.X509_ASN_ENCODING, OIDs.szOID_AUTHORITY_KEY_IDENTIFIER2, ref identifier, 0x8000, IntPtr.Zero, out data, ref dataSize)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } using (data) { var buffer = new byte[dataSize]; Marshal.Copy(data.DangerousGetHandle(), buffer, 0, (int)dataSize); return(buffer); } } finally { Marshal.FreeHGlobal(publicKeyPtr); Marshal.FreeHGlobal(serialNumberPtr); } }
// creates the basic constraints extension. static void CreateAuthorityKeyIdentifierExtension( ref CERT_EXTENSION pExtension, ref CRYPT_DATA_BLOB pKeyId) { // set the certificate as a non-CA certificate. CERT_AUTHORITY_KEY_ID2_INFO keyInfo = new CERT_AUTHORITY_KEY_ID2_INFO(); keyInfo.KeyId.cbData = pKeyId.cbData; keyInfo.KeyId.pbData = pKeyId.pbData; pExtension.pszObjId = szOID_AUTHORITY_KEY_IDENTIFIER2; pExtension.fCritical = 0; GCHandle hKeyInfo = GCHandle.Alloc(keyInfo, GCHandleType.Pinned); IntPtr pData = IntPtr.Zero; int dwDataSize = 0; try { // calculate amount of memory required. int bResult = NativeMethods.CryptEncodeObjectEx( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_AUTHORITY_KEY_IDENTIFIER2, // X509_AUTHORITY_KEY_ID, hKeyInfo.AddrOfPinnedObject(), 0, IntPtr.Zero, IntPtr.Zero, ref dwDataSize); if (bResult == 0) { throw new InvalidOperationException("Could not get size for basic constraints extension."); } // allocate memory. pData = Marshal.AllocHGlobal(dwDataSize); // encode blob. bResult = NativeMethods.CryptEncodeObjectEx( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_AUTHORITY_KEY_IDENTIFIER2, // X509_AUTHORITY_KEY_ID, hKeyInfo.AddrOfPinnedObject(), 0, IntPtr.Zero, pData, ref dwDataSize); if (bResult == 0) { throw new InvalidOperationException("Could not create for basic constraints extension."); } pExtension.Value.cbData = dwDataSize; pExtension.Value.pbData = pData; pData = IntPtr.Zero; } finally { if (pData != IntPtr.Zero) { Marshal.FreeHGlobal(pData); } if (hKeyInfo.IsAllocated) { hKeyInfo.Free(); } } }