Что нового

Работа с System.Security.Cryptography.X509Certificates

Old Shoe

Новичок
Сообщения
1
Репутация
0
Добрый день
Не могу создать объект "System.Security.Cryptography.X509Certificates2.X509Store"
Команда:
Local $oObject = objCreate("System.Security.Cryptography.X509Certificates.X509Certificate")
проходит нормально и возвращает объект "сертификат", но при попытке создания объекта "хранилище сертификатов"
Local $oObject = objCreate("System.Security.Cryptography.X509Certificates.X509Store")
возвращает ошибку.
Думал, что у меня в системе что-то не так, но вот такой пример в PowerShell работает прекрасно:

$store=new-object System.Security.Cryptography.X509Certificates.X509Store("CA")
$store.open("ReadOnly")
$store.Certificates
$store.Certificates.count

Подскажите, пожалуйста, кто знает, что не так делаю?
 

mrsoros

Новичок
Сообщения
28
Репутация
0
Привет. Получилось что-то? Хочу использовать X509Certificates2 для получения сведений о сертификате из cer-файла. Не могу найти примеров. Может у вас есть что-нибудь?
 

johnmarshall

Осваивающий
Сообщения
202
Репутация
39
может не актуально, но все-же:
в powershell работает, потому, что powershell построен на .NET Framework платформе, соответственно, и управляется C#.
что-бы это работало в автоит, нужно создать COM-обертку на C#, зарегистрировать ее в системе, а потом уже создавать comObject,
с помощью которого, собственно и будем вызывать нужные методы, которые тоже нужно создать в той-же обертке на C#.

обертка на c#
Код:
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Collections.Generic;

namespace CertificateHelper
{
  // COM Интерфейс для доступа
  [ComVisible(true)]
  [Guid("12345678-1234-1234-1234-123456789012")]
  [InterfaceType(ComInterfaceType.InterfaceIsDual)]
  public interface ICertificateManager
  {
    int GetCertificateCount(string storeName, string storeLocation);
    string GetCertificateSubject(string storeName, string storeLocation, int index);
    string GetCertificateThumbprint(string storeName, string storeLocation, int index);
    string GetCertificateIssuer(string storeName, string storeLocation, int index);
    bool FindCertificateByThumbprint(string storeName, string storeLocation, string thumbprint);
    string[] GetAllCertificateThumbprints(string storeName, string storeLocation);
    bool IsCertificateValid(string storeName, string storeLocation, string thumbprint);
  }

  // собственно, реализация
  [ComVisible(true)]
  [Guid("87654321-4321-4321-4321-210987654321")]
  [ClassInterface(ClassInterfaceType.None)]
  [ProgId("CertificateHelper.CertificateManager")]
  public class CertificateManager : ICertificateManager
  {
    private X509Store GetStore(string storeName, string storeLocation)
    {
      StoreName name;
      StoreLocation location;

      // парсим имена
      switch (storeName.ToUpper())
      {
        case "MY":
        case "PERSONAL":
          name = StoreName.My;
          break;
        case "ROOT":
          name = StoreName.Root;
          break;
        case "CA":
        case "INTERMEDIATE":
          name = StoreName.CertificateAuthority;
          break;
        default:
          name = StoreName.My;
          break;
      }

      // парсим раположение
      switch (storeLocation.ToUpper())
      {
        case "CURRENTUSER":
          location = StoreLocation.CurrentUser;
          break;
        case "LOCALMACHINE":
          location = StoreLocation.LocalMachine;
          break;
        default:
          location = StoreLocation.CurrentUser;
          break;
      }

      return new X509Store(name, location);
    }

    public int GetCertificateCount(string storeName, string storeLocation)
    {
      try
      {
        using (var store = GetStore(storeName, storeLocation))
        {
          store.Open(OpenFlags.ReadOnly);
          return store.Certificates.Count;
        }
      }
      catch
      {
        return -1;
      }
    }

    public string GetCertificateSubject(string storeName, string storeLocation, int index)
    {
      try
      {
        using (var store = GetStore(storeName, storeLocation))
        {
          store.Open(OpenFlags.ReadOnly);
          if (index >= 0 && index < store.Certificates.Count)
          {
            return store.Certificates[index].Subject;
          }
        }
      }
      catch
      {
        // если ошибка, вернем пустую строку
      }
      return "";
    }

    public string GetCertificateThumbprint(string storeName, string storeLocation, int index)
    {
      try
      {
        using (var store = GetStore(storeName, storeLocation))
        {
          store.Open(OpenFlags.ReadOnly);
          if (index >= 0 && index < store.Certificates.Count)
          {
            return store.Certificates[index].Thumbprint;
          }
        }
      }
      catch
      {
        // если ошибка, вернем пустую строку
      }
      return "";
    }

    public string GetCertificateIssuer(string storeName, string storeLocation, int index)
    {
      try
      {
        using (var store = GetStore(storeName, storeLocation))
        {
          store.Open(OpenFlags.ReadOnly);
          if (index >= 0 && index < store.Certificates.Count)
          {
            return store.Certificates[index].Issuer;
          }
        }
      }
      catch
      {
        // если ошибка, вернем пустую строку
      }
      return "";
    }

    public bool FindCertificateByThumbprint(string storeName, string storeLocation, string thumbprint)
    {
      try
      {
        using (var store = GetStore(storeName, storeLocation))
        {
          store.Open(OpenFlags.ReadOnly);
          var collection = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
          return collection.Count > 0;
        }
      }
      catch
      {
        return false;
      }
    }

    public string[] GetAllCertificateThumbprints(string storeName, string storeLocation)
    {
      try
      {
        using (var store = GetStore(storeName, storeLocation))
        {
          store.Open(OpenFlags.ReadOnly);
          List<string> thumbprints = new List<string>();

          foreach (X509Certificate2 cert in store.Certificates)
          {
            thumbprints.Add(cert.Thumbprint);
          }

          return thumbprints.ToArray();
        }
      }
      catch
      {
        return new string[0];
      }
    }

    public bool IsCertificateValid(string storeName, string storeLocation, string thumbprint)
    {
      try
      {
        using (var store = GetStore(storeName, storeLocation))
        {
          store.Open(OpenFlags.ReadOnly);
          var collection = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);

          if (collection.Count > 0)
          {
            var cert = collection[0];
            return DateTime.Now >= cert.NotBefore && DateTime.Now <= cert.NotAfter;
          }
        }
      }
      catch
      {
        // если ошибка, вернем false
      }
      return false;
    }
  }
}


компилируем, с учетом разрядности x86:
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe" /target:library /platform:x86 /out:CertificateHelper.dll CertificateManager.cs

потом ее регистрируем с учетом разрядности х86:
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe" CertificateHelper.dll /tlb /codebase
если используете /codebase, обязательно подпишите!

собственно, тестируем обязательно, скрипт соберите в 32 бит версии, потому, что и все что выше делали для 32 бит версии:
Код:
; AutoIt скрипт использования COM-обертки DLL для Менеджера сертификатов
#include <MsgBoxConstants.au3>
#include <Array.au3>

; сразу проверяем архитектуру автоита
MsgBox($MB_ICONINFORMATION, "версия AutoIt", "запущено как приложение: " & (@AutoItX64 ? "64-bit" : "32-bit"))

; создаем COM обьект нашей DLL
Local $oCertManager = ObjCreate("CertificateHelper.CertificateManager")

If @error Then
    Local $sErrorMsg = "Ошибка создания CertificateManager COM обьекта." & @CRLF & @CRLF
    $sErrorMsg &= "Код ошибки: " & @error & @CRLF & @CRLF
    $sErrorMsg &= "Варианты решения:" & @CRLF
    $sErrorMsg &= "1. Проверить версию скрипка 32/64" & @CRLF
    $sErrorMsg &= "2. Проверить правильность регистрации regasm.exe:" & @CRLF
    If @AutoItX64 Then
        $sErrorMsg &= "   64-bit: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe" & @CRLF
    Else
        $sErrorMsg &= "   32-bit: C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe" & @CRLF
    EndIf
    $sErrorMsg &= "3. Регистрация от имени Администратора!" & @CRLF
    $sErrorMsg &= "4. Версия .NET Framework нужна 4.0+"

    MsgBox($MB_ICONERROR, "COM Ошибка", $sErrorMsg)
    Exit
EndIf

If Not IsObj($oCertManager) Then
    MsgBox($MB_ICONERROR, "Ошибка", "не удается создать CertificateManager")
    Exit
EndIf

; Пример 1: Вернем кол-во сертификатов
Local $iCount = $oCertManager.GetCertificateCount("MY", "CurrentUser")
MsgBox($MB_ICONINFORMATION, "Всего сертификатов", "Личных (текуший пользователь): " & $iCount)

; Пример 2: Читаем доп. сведения:
If $iCount > 0 Then
    ConsoleWrite("=== Личные сертификаты (текуший пользователь) ===" & @CRLF)

    For $i = 0 To $iCount - 1
        Local $sSubject = $oCertManager.GetCertificateSubject("MY", "CurrentUser", $i)
        Local $sIssuer = $oCertManager.GetCertificateIssuer("MY", "CurrentUser", $i)
        Local $sThumbprint = $oCertManager.GetCertificateThumbprint("MY", "CurrentUser", $i)

        ConsoleWrite("Сертификат " & ($i + 1) & ":" & @CRLF)
        ConsoleWrite("  Субьект: " & $sSubject & @CRLF)
        ConsoleWrite("  Издатель: " & $sIssuer & @CRLF)
        ConsoleWrite("  Отпечаток: " & $sThumbprint & @CRLF)
        ConsoleWrite("" & @CRLF)
    Next
EndIf

MsgBox($MB_ICONINFORMATION, "Информация", "Завершено.")


все.
 

mrsoros

Новичок
Сообщения
28
Репутация
0
Круто конечно. Но надо на 1000 машинах привести систему в соответствие требованиям чтобы скрипт сработал. Сложновато... Я пока остановился на использовании стандартных утилит CertMgr.Exe и certutil.exe. Делать Run CertMgr.Exe/certutil.exe и отлавливать их stdout в скрипте.
 
Верх