Как создать и установить самоподписанные сертификаты X.509 в Windows 10 без участия пользователя? - PullRequest
0 голосов
/ 14 декабря 2018

Проблема

  • Создание и установка временных сертификатов для подписи кода в моей среде разработки.
  • Это должно быть сделано с помощью автоматического сценария (без взаимодействия с пользователем).

Устаревший сценарий

Сейчас у меня естьэтот сценарий, который создает сертификаты с помощью устаревшего инструмента makecert :

makecert -r -pe -n "CN=My CA" -ss CA -sr CurrentUser -a sha256 -cy authority -sky signature -sv MyCA.pvk MyCA.cer
certutil -user -addstore Root MyCA.cer
certutil -addstore Root MyCA.cer
makecert -pe -n "CN=My Company" -a sha256 -cy end -sky signature -ic MyCA.cer -iv MyCA.pvk -sv MySPC.pvk MySPC.cer
pvk2pfx.exe -pvk MySPC.pvk -spc MySPC.cer -pfx MySPC.pfx
certutil -f -user -p "" -importPFX MySPC.pfx

Приведенный выше сценарий создает 2 сертификата:

  1. MyCA.cer: самоподписанный сертификат корневого центра.
  2. MySPC.cer: Сертификат для подписи моего кода (подписан MyCA.cer).

Этот сценарий также открывает диалоговые окна, запрашивающие пароль пользователя и подтверждение пользователя для установки сертификатав хранилище доверенных корневых центров сертификации. Мне нужно это сделать без взаимодействия с пользователем .

Новый скрипт

Следуя этой инструкции , я переписал унаследованный скрипт с помощью командлета powershell New-SelfSignedCertificate.Вот что я попробовал:

# Create a self-signed root authority certificate.
$rootCert = New-SelfSignedCertificate -KeyExportPolicy Exportable -CertStoreLocation cert:\CurrentUser\My -DnsName "Development Root CA" -NotAfter (Get-Date).AddYears(5) -KeyusageProperty All -KeyUsage CertSign,CRLSign,DigitalSignature

# Export the root authority private key.
[System.Security.SecureString] $password = ConvertTo-SecureString -String "passwordx" -Force -AsPlainText
[String] $rootCertPath = Join-Path -Path cert:\CurrentUser\My\ -ChildPath "$($rootcert.Thumbprint)"
Export-PfxCertificate -Cert $rootCertPath -FilePath "MyCA.pfx" -Password $password
Export-Certificate -Cert $rootCertPath -FilePath "MyCA.crt"

# Create a "MySPC" certificate signed by our root authority.
$cert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "MySPC" -TextExtension @("2.5.29.19={text}false") -KeyLength 2048 -Signer $rootCert -Type CodeSigningCert -KeyUsage None

# Save the signed certificate with private key into a PFX file and just the public key into a CRT file.
[String] $certPath = Join-Path -Path cert:\LocalMachine\My\ -ChildPath "$($cert.Thumbprint)"
Export-PfxCertificate -Cert $certPath -FilePath MySPC.pfx -Password $password
Export-Certificate -Cert $certPath -FilePath "MySPC.crt"

# Add MyCA certificate to the Trusted Root Certification Authorities.
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.import("MyCA.pfx", $password, "Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store(
    [System.Security.Cryptography.X509Certificates.StoreName]::Root,
    "localmachine"
)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()

# Import certificate.
Import-PfxCertificate -FilePath MySPC.pfx cert:\CurrentUser\My -Password $password

Новый скрипт создает и устанавливает MyCA.cer и MySPC.cer без взаимодействия с пользователем, но эти сертификаты не совпадают с предыдущими.Например, когда я смотрю на MyCA.cer, предполагаемые цели:

Proves your identity to a remote computer
Ensures the identity of a remote computer
All issuance policies

Вместо ожидаемого:

All issuance policies
All application policies

Другие проблемы

  • С makecert сертификат создается с Основным ограничением: Subject Type=CA, но я не могу создать такое ограничение с помощью New-SelfSignedCertificate.

  • Наконец, MySPC.cer не может подписать мой код, происходит сбой с ошибкой типа «недопустимо для выбранной цели».

Вопрос

Как я могу сгенерировать те же сертификаты, что и унаследованный скрипт, но без присмотра?

Заранее спасибо.

РЕДАКТИРОВАТЬ

С изменениями, предложенными Mötz, я могу подписать, но при проверке возникает ошибка.Это команды:

Команда подписи

signtool.exe sign /v /a c:\git\...\Win32\det.dll

The following certificate was selected:
    Issued to: XXXXXXXXXX
    Issued by: My CA
    Expires:   Fri Dec 20 20:18:26 2019
    SHA1 hash: 0440F2B76E5BBF1F9CB4D24EF5E5AA54F4F4C2E1

Done Adding Additional Store
Successfully signed: c:\git\...\Win32\det.dll

Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0

Команда проверки

signtool.exe verify /pa /v c:\git\...\Win32\det.dll

Signature Index: 0 (Primary Signature)
Hash of file (sha1): E4EC8126CC9510610AF4FC72CC8722B81B171AE1

Signing Certificate Chain:
    Issued to: My CA
    Issued by: My CA
    Expires:   Thu Dec 21 01:14:52 2023
    SHA1 hash: DA5B1972016D66294886CA3EDA2D4FEF245D7337

        Issued to: XXXXXXXXX
        Issued by: My CA
        Expires:   Sat Dec 21 01:24:53 2019
        SHA1 hash: 3316486BAF0A53C1C3227F1E522FF776B6F32CC9

File is not timestamped.

SignTool Error: The signing certificate is not valid for the requested usage.

Number of files successfully Verified: 0
Number of warnings: 0
Number of errors: 1

Решение

Принятое решение включает в себя все ключевые вещи для решения проблемы (огромное спасибо Mötz).Я включаю свой последний сценарий с небольшими изменениями, чтобы помочь другим.

#
# This script will create and install two certificates:
#     1. `MyCA.cer`: A self-signed root authority certificate. 
#     2. `MySPC.cer`: The cerificate to sign code in 
#         a development environment (signed with `MyCA.cer`).
# 
# No user interaction is needed (unattended). 
# Powershell 4.0 or higher is required.
#

# Define the expiration date for certificates.
$notAfter = (Get-Date).AddYears(10)

# Create a self-signed root Certificate Authority (CA).
$rootCert = New-SelfSignedCertificate -KeyExportPolicy Exportable -CertStoreLocation Cert:\CurrentUser\My -DnsName "My CA" -NotAfter $notAfter -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}CA=1") -KeyusageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature

# Export the CA private key.
[System.Security.SecureString] $password = ConvertTo-SecureString -String "passwordx" -Force -AsPlainText
[String] $rootCertPath = Join-Path -Path cert:\CurrentUser\My\ -ChildPath "$($rootcert.Thumbprint)"
Export-PfxCertificate -Cert $rootCertPath -FilePath "MyCA.pfx" -Password $password
Export-Certificate -Cert $rootCertPath -FilePath "MyCA.crt"

# Create an end certificate signed by our CA.
$cert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "My Company Name" -NotAfter $notAfter -Signer $rootCert -Type CodeSigningCert -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}CA=0&pathlength=0")

# Save the signed certificate with private key into a PFX file and just the public key into a CRT file.
[String] $certPath = Join-Path -Path cert:\LocalMachine\My\ -ChildPath "$($cert.Thumbprint)"
Export-PfxCertificate -Cert $certPath -FilePath "MySPC.pfx" -Password $password
Export-Certificate -Cert $certPath -FilePath "MySPC.crt"

# Add MyCA certificate to the Trusted Root Certification Authorities.
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.import("MyCA.pfx", $password, "Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store(
    [System.Security.Cryptography.X509Certificates.StoreName]::Root,
    "localmachine"
)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()

# Remove MyCA from CurrentUser to avoid issues when signing with "signtool.exe /a ..."
Remove-Item -Force "cert:\CurrentUser\My\$($rootCert.Thumbprint)"

# Import certificate.
Import-PfxCertificate -FilePath MySPC.pfx cert:\CurrentUser\My -Password $password -Exportable

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Я только что проверил ваш код с помощью signtool.exe, полученного из моей установки Visual Studio 2017, и кажется, что все работает.

Так что мне бы очень хотелось увидеть код / ​​команду, которую вы используете для подписи файлов.Еще больше я хотел бы увидеть реальный вывод ошибки, которую вы видите.Не могли бы вы сначала попробовать подписать процесс вручную / вручную, чтобы мы были уверены, что сосредоточены на правильном вопросе?

С учетом сказанного я потратил некоторое время на поиски ответов на некоторые другие ваши вопросы.had.

Решение первой части о том, что вы хотите видеть только

All issuance policies
All application policies

Это решается с помощью параметра TextExtension:

-TextExtension @("2.5.29.37={text}1.3.6.1.4.1.311.10.12.1")

Решение нужной части

Subject Type = CA

Это решается с помощью параметра TextExtension:

-TextExtension @("2.5.29.19={text}CA=1&pathlength=3")

Длина пути используется для ограничения количества уровней дочерних элементов, которые могут использовать сертификат.Пожалуйста, прочитайте больше здесь .Значение 3 - это просто что-то, что используется при тестировании.

Затем нам нужно объединить эти две разные записи TextExtensions:

-TextExtension @("2.5.29.37={text}1.3.6.1.4.1.311.10.12.1", "2.5.29.19={text}CA=1&pathlength=3")

, что заставит нас написать обновленный скрипт, подобный этому

$rootCert = New-SelfSignedCertificate -KeyExportPolicy Exportable -CertStoreLocation cert:\CurrentUser\My -DnsName "Development Root CA" -NotAfter (Get-Date).AddYears(5) -TextExtension @("2.5.29.37={text}1.3.6.1.4.1.311.10.12.1", "2.5.29.19={text}CA=1&pathlength=3") -KeyusageProperty All -KeyUsage CertSign,CRLSign,DigitalSignature

# Export the root authority private key.
[System.Security.SecureString] $password = ConvertTo-SecureString -String "passwordx" -Force -AsPlainText
[String] $rootCertPath = Join-Path -Path cert:\CurrentUser\My\ -ChildPath "$($rootcert.Thumbprint)"
Export-PfxCertificate -Cert $rootCertPath -FilePath "MyCA.pfx" -Password $password
Export-Certificate -Cert $rootCertPath -FilePath "MyCA.crt"

# Create a "MySPC" certificate signed by our root authority.
$cert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "MySPC" -Signer $rootCert -Type CodeSigningCert

# Save the signed certificate with private key into a PFX file and just the public key into a CRT file.
[String] $certPath = Join-Path -Path cert:\LocalMachine\My\ -ChildPath "$($cert.Thumbprint)"
Export-PfxCertificate -Cert $certPath -FilePath MySPC.pfx -Password $password
Export-Certificate -Cert $certPath -FilePath "MySPC.crt"

# Add MyCA certificate to the Trusted Root Certification Authorities.
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.import("MyCA.pfx", $password, "Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store(
    [System.Security.Cryptography.X509Certificates.StoreName]::Root,
    "localmachine"
)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()

# Import certificate.
Import-PfxCertificate -FilePath MySPC.pfx cert:\CurrentUser\My -Password $password

Но, как я уже говорил ранее, ваш код, похоже, генерирует правильные сертификаты, потому что я смог использовать сгенерированный им сертификат и подписать с ним файл .net EXE.

До этогоподпись

Before signing

Подпись

SignTool sign /n "MySPC" 2LCS.exe

После подписания

After signing

Обновление на основе новой информации

Вам необходимо указать ключ / pa в команде проверки,

https://knowledge.digicert.com/solution/SO21771.html

https://docs.microsoft.com/en-us/windows/desktop/seccrypto/signtool

Вопрос: вы бы увидели то же самое с сертификатами makecert?

Обновлено с рабочим кодом

Ваша ориентация на свойствах сертификата вывела меня на неверный путь.Основываясь на обсуждении здесь , я узнал, что нам может нужно создать его как подпись кода класса 3.Я удалил расширение 1.3.6.1.4.1.311.10.12.1 EKU и заменил его на 1.3.6.1.5.5.7.3.3 .Пожалуйста, смотрите пример кода ниже.

$rootCert = New-SelfSignedCertificate -KeyExportPolicy Exportable -CertStoreLocation cert:\CurrentUser\My -DnsName "Development Root CA" -NotAfter (Get-Date).AddYears(5) -TextExtension @("2.5.29.19={text}CA=1&pathlength=3", "2.5.29.37={text}1.3.6.1.5.5.7.3.3") -KeyusageProperty All -KeyUsage CertSign,CRLSign,DigitalSignature #-Type CodeSigningCert

# Export the root authority private key.
[System.Security.SecureString] $password = ConvertTo-SecureString -String "passwordx" -Force -AsPlainText
[String] $rootCertPath = Join-Path -Path cert:\CurrentUser\My\ -ChildPath "$($rootcert.Thumbprint)"
Export-PfxCertificate -Cert $rootCertPath -FilePath "MyCA.pfx" -Password $password
Export-Certificate -Cert $rootCertPath -FilePath "MyCA.crt"

# Create a "MySPC" certificate signed by our root authority.
$cert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "MySPC" -Signer $rootCert -Type CodeSigningCert

# Save the signed certificate with private key into a PFX file and just the public key into a CRT file.
[String] $certPath = Join-Path -Path cert:\LocalMachine\My\ -ChildPath "$($cert.Thumbprint)"
Export-PfxCertificate -Cert $certPath -FilePath MySPC.pfx -Password $password
Export-Certificate -Cert $certPath -FilePath "MySPC.crt"

# Add MyCA certificate to the Trusted Root Certification Authorities.
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.import("MyCA.pfx", $password, "Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store(
    [System.Security.Cryptography.X509Certificates.StoreName]::Root,
    "localmachine"
)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()

# Import certificate.
Import-PfxCertificate -FilePath MySPC.pfx cert:\CurrentUser\My -Password $password

Я выполнил следующую команду подписи:

enter image description here

И после этого я запустил проверкукоманда:

enter image description here

С этим я считаю, что у вас должен быть рабочий раствор.Пожалуйста, проверьте его, затем подтвердите, а затем расширьте, чтобы включить также вашу подпись с отметкой времени.

0 голосов
/ 17 декабря 2018

Установка сертификата в хранилище сертификатов выполняется службой распространения сертификатов.

Таким образом, вы можете сканировать (Scan API) службу распространения сертификатов и разрабатывать ее так же.

Вы можете использовать API Monitor.

...