예제 #1
0
 public static extern bool CryptEncodeObjectEx
 (
     [param: In, MarshalAs(UnmanagedType.U4)] EncodingType dwCertEncodingType,
     [param: In, MarshalAs(UnmanagedType.LPStr)] string lpszStructType,
     [param: In, MarshalAs(UnmanagedType.Struct)] ref CERT_ALT_NAME_INFO pvStructInfo,
     [param: In, MarshalAs(UnmanagedType.U4)] uint dwFlags,
     [param: In, MarshalAs(UnmanagedType.SysInt)] IntPtr pEncodePara,
     [param: Out] out LocalBufferSafeHandle pvEncoded,
     [param: In, Out, MarshalAs(UnmanagedType.U4)] ref uint pcbEncoded
 );
 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(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(altNames[index].Value)
                     };
                     unionValues.Add(altName.Value.pwszURL);
                     break;
             }
             Marshal.StructureToPtr(altName, IntPtrArithmetic.Add(altNamesBuffer, offset), false);
         }
         certAltName.rgAltEntry = altNamesBuffer;
         uint dataSize = 0;
         byte[] 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("Failed to encode object.");
         }
         return data;
     }
     finally
     {
         Marshal.FreeHGlobal(altNamesBuffer);
         unionValues.ForEach(Marshal.FreeHGlobal);
     }
 }
 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);
     }
 }