Я пытаюсь извлечь информацию о расширениях сертификатов X509 из Microsoft CA, используя Powershell.Это подтверждение концепции больше всего на свете.
Я использовал COM-объект CertificateAuthority.View
для доступа к базе данных CA, затем перечислил каждую строку в таблице расширений с помощью EnumCertViewExtension(0)
, чтобы получить доступ кколонны.Я извлекаю значения столбца с помощью GetValue(PROTOTYPE_BINARY,CV_OUT_BASE)
, который возвращает значение расширения в виде строки в кодировке Base64.
Вышеприведенное работает, поскольку я могу декодировать эти данные Base64, используя System.Security.Cryptography.AsnEncodedData
, как показано в первой частииз примера ниже.Недостатком этого метода является то, что он возвращает значения только как одну строку для каждой точки распространения (в формате, аналогичном утилите certutil.exe
), поэтому при извлечении URL-адреса может потребоваться дальнейший анализ этой строки с помощью регулярного выражения или аналогичного.
Моя альтернативная мысль - попытаться декодировать данные с помощью CertificateAuthority.EncodeCRLDistInfo
, поскольку я успешно использовал другие расширения и COM-объекты при преобразовании значений в XML и / или JSON, которыми впоследствии легче манипулировать.
Однако этот конкретный параметр дает странные результаты.Кажется, что он полностью декодирует первую строку Base64 в массиве, но не может сделать это для остальных трех строк.
Следующий пример MCV показывает это.
# These are the raw Base64 encoded values for the CRL Distribution Point extension as extracted
# from the CA's Db by enumerating CertificateAuthority.View.1
$cdpArr = @(
"MD4wPKA6oDiGNmh0dHA6Ly9wa2kud2luZG93cy50ZXN0L2NkcC9XaW5UZXN0LUlzc3VpbmctQ0EyKDEpLmNybA==",
"MDswOaA3oDWGM2h0dHA6Ly9wa2kud2luZG93cy50ZXN0L2NkcC9XaW5UZXN0LUlzc3VpbmctQ0EyLmNybA==",
"MDswOaA3oDWGM2h0dHA6Ly9wa2kud2luZG93cy50ZXN0L2NkcC9XaW5kb3dzVGVzdC1Sb290LUNBLmNybA==",
"MDkwN6A1oDOGMWh0dHA6Ly9wa2kud2luZG93cy50ZXN0L2NkcC9XaW5UZXN0LVBvbGljeS1DQS5jcmw="
)
# The next three lines display all four CRL Distribution Points, so the input data must be good.
Foreach ($cdp in $cdpArr) {
$cdpASN = New-Object System.Security.Cryptography.AsnEncodedData("2.5.29.31",[convert]::FromBase64String($cdp))
$cdpASN.format($true)
}
# The following only displays one CRL Distribution Point URL
Foreach ($cdp in $cdpArr) {
$cdpObj = new-object -ComObject CertificateAuthority.EncodeCRLDistInfo
$cdpASN = New-Object System.Security.Cryptography.AsnEncodedData("2.5.29.31",[convert]::FromBase64String($cdp))
$bString = ([system.text.encoding]::Unicode).GetString($cdpASN.RawData)
$cdpObj.Decode($bString)
For ($i=0; $i -lt $cdpObj.GetDistPointCount(); $i++){
For ($j=0; $j -lt $cdpObj.GetNameCount($i); $j++) {
"CDP {0}, Name {1}, Choice {2}, URL {3}" -f $i, $j, $cdpObj.GetNameChoice($i,$j), $cdpObj.GetName($i,$j)
}
}
Remove-Variable cdpASN, cdpObj # just in-case something lingers
}
Первая часть возвращаетниже показано, что все четыре точки распространения успешно декодируются, но, к сожалению, в виде четырех строк:
[1]CRL Distribution Point
Distribution Point Name:
Full Name:
URL=http://pki.windows.test/cdp/WinTest-Issuing-CA2(1).crl
[1]CRL Distribution Point
Distribution Point Name:
Full Name:
URL=http://pki.windows.test/cdp/WinTest-Issuing-CA2.crl
[1]CRL Distribution Point
Distribution Point Name:
Full Name:
URL=http://pki.windows.test/cdp/WindowsTest-Root-CA.crl
[1]CRL Distribution Point
Distribution Point Name:
Full Name:
URL=http://pki.windows.test/cdp/WinTest-Policy-CA.crl
Вторая часть возвращает следующее, показывая URL-адрес первой точки распространения, но ни одну из последующих.
CDP 0, Name 0, Choice 7, URL http://pki.windows.test/cdp/WinTest-Issuing-CA2(1).crl
CDP 0, Name 0, Choice 7, URL
CDP 0, Name 0, Choice 7, URL
CDP 0, Name 0, Choice 7, URL
Если я переставлю порядок в массиве, то полностью успешное декодирование будет соответственно изменено, то есть первая строка в массиве, как показано выше, всегда полностью декодируется независимо от ее положения, в то время как остальные три не отображаютсяURL.
Первые мысли предполагают проблему со строками Base64 - но все они полностью декодируются с помощью первого метода, исключая это.
Следующим в списке совпадений будет преобразование строк вокруг[system.text.encoding]::Unicode
, но во всех случаях ASN.1 должен успешно декодироваться как метод GetNameChoice()
d всегда возвращает 7, фактически исключая это (возможно!).
Это ошибка или я что-то пропустил?