Ребята, подскажите пожалуйста как в 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,
}
Комментариев нет:
Отправить комментарий