web-dev-qa-db-ja.com

ユーザーの操作なしでWindows 10でX.509自己署名証明書を作成およびインストールする方法

問題

  • 開発環境でコードに署名するための一時的な証明書を作成してインストールします。
  • これは、無人スクリプトを使用して実行する必要があります(ユーザーとの対話なし)。

従来のスクリプト

現在、 非推奨のツール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によって提案された変更により、署名することはできますが、検証でエラーが発生します。これらはコマンドです:

Signコマンド

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
9
Cartucho

Visual Studio 2017のインストールからのsigntool.exeでコードをテストしたところ、問題はないようです。

だから私は本当にあなたがファイルに署名するために使用するコード/コマンドを見たいです。さらに、あなたが見ているエラーからの実際の出力を確認したいと思います。最初に手動または手動で署名プロセスを試していただけますか?私たちは正しい問題に焦点を当てていると確信していますか?

そうは言っても、私はあなたが持っていた他のいくつかの質問に答えるために少し時間をかけて掘り下げました。

見たいだけの最初の部分を解く

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は、テスト中に使用されるものです。

次に、これらの2つの異なる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

新しい情報に基づいて更新します

Verifyコマンドで/ paスイッチを指定する必要があります。

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

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

質問は、makecert証明書でも同じであるかどうかです。

作業コードで更新されました

証明書の特性に焦点を当てたので、私は間違った道を進みました。 ここ からの議論に基づいて、私はmightをクラス3コード署名として作成する必要があることを学びました。 1.3.6.1.4.1.311.10.12.1EKU拡張機能を削除して、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

それが整ったら、私はあなたが実用的な解決策を持つべきだと信じています。テストして検証し、タイムスタンプ署名を含めるように拡張してください。

4
Mötz

証明書ストアへの証明書のインストールは、証明書伝播サービスによって行われます。

したがって、スキャンAPI(スキャンAPI)証明書伝播サービスをスキャンして、そのように開発できます。

API Monitorを使用できます。

0
VOLVO