Страницы

Поиск по вопросам

суббота, 9 марта 2019 г.

Установка списка отзывов (*.crl) в хранилище компьютера

Ребята, подскажите пожалуйста как в C# установить *.crl в хранилище компьютера. Есть код для установки сертификата в корневые сертификаты:
private static void InstallRootCertificate(string cerFileName) { X509Store store = new X509Store(StoreName.AuthRoot, StoreLocation.LocalMachine); X509Certificate2 certificate = new X509Certificate2(cerFileName); store.Open(OpenFlags.ReadWrite); store.Add(certificate); store.Close(); }
Но он, по понятным причинам не подходит для crl. Заранее спасибо.


Ответ

Хотя вопрос был задан очень давно, и уже, возможно, не актуален, все же предложу решение, поскольку проблема интересная. Ее решение может быть полезно, например, когда нужно автоматизировать обновление списков отозванных сертификатов на десятках серверов.
К сожалению, никаких стандартных средств для решения этой задачи .NET не предоставляет. Придется использовать обертки для crypt32.dll и unsafe-код. Ниже приведет пример решения. Его основу составляет класс CrlFile, который позволят открыть crl-файл и импортировать его в стандартное хранилище (класс System.Security.Cryptography.X509Certificates.X509Store).
Дополнительная информация:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa376011(v=vs.85).aspx https://blogs.msdn.com/b/gproano/archive/2005/03/22/400645.aspx?Redirected=true

class Program { static void Main(string[] args) { var store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite);
var crl = new CrlFile(@"d:\tmp\ca
oot.crl"); crl.Import(store, CrlAddDisposition.CERT_STORE_ADD_REPLACE_EXISTING); store.Close(); } }
public class CrlFile { // по уму здесь нужна реализация SafeHandle, // но чтобы не удлинять код оставим, как есть private IntPtr _context;
private readonly string _file;
public CrlFile(string file) { _file = file; }
public bool Import(X509Store store, CrlAddDisposition disp, ref IntPtr storeContext) { EnsureCrlContext(); return Crypto32Interop.CertAddCRLContextToStore(store.StoreHandle, _context, (uint)disp, storeContext); }
public bool Import(X509Store store, CrlAddDisposition disp) { var storeContext = IntPtr.Zero; return Import(store, disp, ref storeContext); }
private unsafe void EnsureCrlContext() { if (_context != IntPtr.Zero) return;
var context = new IntPtr(Crypto32Interop.CERT_QUERY_CONTENT_CRL);
var handle = GCHandle.Alloc(_file, GCHandleType.Pinned); var data = handle.AddrOfPinnedObject();
bool ret = Crypto32Interop.CryptQueryObject( Crypto32Interop.CERT_QUERY_OBJECT_FILE, data, Crypto32Interop.CERT_QUERY_CONTENT_FLAG_CRL, Crypto32Interop.CERT_QUERY_FORMAT_FLAG_ALL, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, new IntPtr(&context));
_context = Crypto32Interop.CertDuplicateCRLContext(context); Crypto32Interop.CertFreeCRLContext(context); handle.Free(); }
~CrlFile() { if (_context != IntPtr.Zero) Crypto32Interop.CertFreeCRLContext(_context); } }
public static class Crypto32Interop { public const uint CERT_QUERY_CONTENT_CTL = 2; public const uint CERT_QUERY_CONTENT_CRL = 3;
public const uint CERT_QUERY_OBJECT_FILE = 1;
public const uint CERT_QUERY_FORMAT_BINARY = 1; public const uint CERT_QUERY_FORMAT_BASE64_ENCODED = 2; public const uint CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED = 3;
public const uint CERT_QUERY_CONTENT_FLAG_CRL = (1 << (int)CERT_QUERY_CONTENT_CRL); public const uint CERT_QUERY_CONTENT_FLAG_CTL = (1 << (int)CERT_QUERY_CONTENT_CTL); public const uint CERT_QUERY_FORMAT_FLAG_BINARY = (1 << (int)CERT_QUERY_FORMAT_BINARY); public const uint CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED = (1 << (int)CERT_QUERY_FORMAT_BASE64_ENCODED); public const uint CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED = (1 << (int)CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED); public const uint CERT_QUERY_FORMAT_FLAG_ALL = (CERT_QUERY_FORMAT_FLAG_BINARY | CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED | CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CertDuplicateCRLContext(IntPtr pCrlContext);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CertFreeCRLContext(IntPtr pCrlContext);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CertAddCRLContextToStore( [In] IntPtr hCertStore, [In] IntPtr pCrlContext, [In] uint dwAddDisposition, [Out] IntPtr ppStoreContext);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptQueryObject( [In] uint dwObjectType, [In] IntPtr pvObject, [In] uint dwExpectedContentTypeFlags, [In] uint dwExpectedFormatTypeFlags, [In] uint dwFlags, [Out] IntPtr pdwMsgAndCertEncodingType, [Out] IntPtr pdwContentType, [Out] IntPtr pdwFormatType, [In, Out] IntPtr phCertStore, [In, Out] IntPtr phMsg, [In, Out] IntPtr ppvContext); }
public enum CrlAddDisposition : uint { CERT_STORE_ADD_NEW = 1, CERT_STORE_ADD_USE_EXISTING = 2, CERT_STORE_ADD_REPLACE_EXISTING = 3, CERT_STORE_ADD_ALWAYS = 4, CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES = 5, CERT_STORE_ADD_NEWER = 6, CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES = 7, }

Комментариев нет:

Отправить комментарий