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); } }
private static byte[] EncodeExtension(IList <X509AlternativeName> altNames) { var certAltName = new CERT_ALT_NAME_INFO(); certAltName.cAltEntry = (uint)altNames.Count; var structSize = Marshal.SizeOf(typeof(CERT_ALT_NAME_ENTRY)); var altNamesBuffer = Marshal.AllocHGlobal(structSize * altNames.Count); var unionValues = new List <IntPtr>(); try { for (int index = 0, offset = 0; index < altNames.Count; index++, offset += structSize) { var altName = new CERT_ALT_NAME_ENTRY(); altName.dwAltNameChoice = (CertAltNameChoice)altNames[index].Type; switch (altName.dwAltNameChoice) { case CertAltNameChoice.CERT_ALT_NAME_DNS_NAME: altName.Value = new CERT_ALT_NAME_ENTRY_UNION { pwszDNSName = Marshal.StringToHGlobalUni((string)altNames[index].Value) }; unionValues.Add(altName.Value.pwszDNSName); break; case CertAltNameChoice.CERT_ALT_NAME_URL: altName.Value = new CERT_ALT_NAME_ENTRY_UNION { pwszURL = Marshal.StringToHGlobalUni((string)altNames[index].Value) }; unionValues.Add(altName.Value.pwszURL); break; case CertAltNameChoice.CERT_ALT_NAME_IP_ADDRESS: var ip = (IPAddress)altNames[index].Value; var addressBytes = ip.GetAddressBytes(); var ipBytes = Marshal.AllocHGlobal(addressBytes.Length); Marshal.Copy(addressBytes, 0, ipBytes, addressBytes.Length); altName.Value = new CERT_ALT_NAME_ENTRY_UNION { IPAddress = new CRYPTOAPI_BLOB { cbData = (uint)addressBytes.Length, pbData = ipBytes } }; unionValues.Add(ipBytes); break; } Marshal.StructureToPtr(altName, IntPtrArithmetic.Add(altNamesBuffer, offset), false); } certAltName.rgAltEntry = altNamesBuffer; uint dataSize = 0; LocalBufferSafeHandle data; if (!Crypt32.CryptEncodeObjectEx(EncodingType.X509_ASN_ENCODING, OIDs.szOID_SUBJECT_ALT_NAME2, ref certAltName, 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(altNamesBuffer); unionValues.ForEach(Marshal.FreeHGlobal); } }