web-dev-qa-db-fra.com

Comment créer et installer des certificats auto-signés X.509 dans Windows 10 sans interaction de l'utilisateur?

Le problème

  • Créez et installez des certificats temporaires pour signer le code Dans mon environnement de développement. 
  • Cela doit être fait avec un script unattended (Sans interaction de l'utilisateur).

Le script hérité

À l’heure actuelle, j’ai ce script qui crée les certificats à l’aide de l’outil obsolète 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

Le script ci-dessus crée 2 certificats:

  1. MyCA.cer: un certificat d'autorité racine auto-signé. 
  2. MySPC.cer: Le certificat pour signer mon code (signé avec MyCA.cer).

Ce script ouvre également des boîtes de dialogue demandant un mot de passe d'utilisateur et une confirmation de l'utilisateur pour installer le certificat dans le magasin d'autorités de certification racines de confiance. J'ai besoin que cela se fasse sans interaction de l'utilisateur

Le nouveau script

En suivant ces instructions , j’ai réécrit le script hérité avec l’applet de commande powershell New-SelfSignedCertificate. C'est ce que j'ai essayé:

# 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

Le nouveau script crée et installe MyCA.cer et MySPC.cer sans interaction de l'utilisateur, mais ces certificats ne sont pas identiques aux précédents. Par exemple, lorsque je regarde MyCA.cer, les objectifs visés sont les suivants:

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

Plutôt que prévu:

All issuance policies
All application policies

D'autres problèmes

  • Avec makecert, le certificat est créé avec la contrainte de base: Subject Type=CA, mais je ne peux pas créer une telle contrainte à l'aide de New-SelfSignedCertificate

  • Enfin, le MySPC.cer est incapable de signer mon code, il échoue avec une erreur Du type "non valide pour le but sélectionné".

La question

Comment puis-je générer les mêmes certificats que le script existant, mais sans surveillance?

Merci d'avance.

MODIFIER 

Avec les modifications proposées par Mötz, je peux signer mais l'erreur est générée lors de la validation. Ce sont les commandes:

Commande de commande

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

Commande de validation

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

La solution

La solution acceptée inclut tous les éléments clés pour résoudre le problème (un grand merci à Mötz). J'inclus mon dernier script avec des modifications mineures pour aider les autres. 

#
# 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
6
Cartucho

Je viens de tester votre code avec le fichier signtool.exe provenant de mon installation de Visual Studio 2017 et tout semble fonctionner.

Donc, j'aimerais vraiment voir le code/la commande que vous utilisez pour signer les fichiers. Encore plus, j'aimerais voir le résultat réel de l'erreur que vous constatez. Pourriez-vous essayer votre processus de signature manuellement/manuellement au début, pour que nous soyons sûrs de nous concentrer sur le bon problème?

Cela dit, j'ai passé un peu de temps à creuser pour répondre à certaines de vos autres questions.

Résoudre la première partie de vous voulant seulement voir 

All issuance policies
All application policies

Ceci est résolu avec le paramètre TextExtension:

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

Résoudre la partie que vous vouliez le 

Subject Type = CA

Ceci est résolu avec le paramètre TextExtension:

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

La longueur du chemin est utilisée pour limiter le nombre d'enfants pouvant utiliser le certificat. S'il vous plaît lire plus ici . La valeur 3 est juste quelque chose est utilisé lors des tests.

Nous devons ensuite combiner ces 2 entrées TextExtensions différentes:

-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")

Ce qui nous fera écrire le script mis à jour comme ceci

$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

Mais comme je l’ai dit plus tôt, votre code semble générer les bons certificats car j’ai pu utiliser le certificat qu’il a généré et signer un fichier EXE .net avec celui-ci.

Avant de signer

 Before signing

Signature

SignTool sign /n "MySPC" 2LCS.exe

Après avoir signé

 After signing

Mise à jour basée sur les nouvelles informations

Vous devez spécifier le commutateur/pa sur votre commande de vérification. 

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

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

La question est de savoir si vous verriez la même chose avec les certificats makecert? 

Mis à jour avec le code de travail

Votre attention sur les propriétés du certificat m'a conduit dans la mauvaise voie. Sur la base d’une discussion de ici j’ai appris que nous pourrions avoir besoin de l’avoir créé comme signature de code de classe 3. J'ai supprimé l'extension 1.3.6.1.4.1.311.10.12.1 EKU et l'ai remplacée par 1.3.6.1.5.5.7.3.3. S'il vous plaît voir ci-dessous exemple de code.

$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

J'ai exécuté la commande de signature suivante:

 enter image description here

Et après cela, j'ai exécuté la commande de vérification:

 enter image description here

Cela dit, vous devriez avoir une solution efficace. Veuillez le tester, le vérifier, puis l'étendre pour inclure également votre signature d'horodatage.

2
Mötz

Installation du certificat sur cert store fait par le service de propagation de certificat.

Vous pouvez donc analyser le service de propagation de certificats (API d'analyse) et le développer.

Vous pouvez utiliser API Monitor.

0
VOLVO