2020-03-25 02:08:37 +08:00
# Copyright (c) Microsoft Corporation.
2018-02-14 01:23:53 +08:00
# Licensed under the MIT License.
# Utility to generate a self-signed certificate and sign a given package such as PowerShell.zip/appx/msi
2016-06-07 00:54:25 +08:00
[ CmdletBinding ( ) ]
param (
2017-01-17 05:31:14 +08:00
#Path to package - Ex: PowerShell.msi, PowerShell.appx
[ Parameter ( Mandatory = $true ) ]
2016-06-07 00:54:25 +08:00
[ ValidateNotNullOrEmpty ( ) ]
[ string ] $PackageFilePath
)
# function to generate a self-signed certificate
# customize parameters to makecert.exe to control certificate life time and other options
function New-SelfSignedCertificate
{
[ CmdletBinding ( ) ]
param (
2017-01-17 05:31:14 +08:00
#Path to save generated Certificate
2016-06-07 00:54:25 +08:00
[ ValidateNotNullOrEmpty ( ) ]
2020-01-14 03:24:10 +08:00
[ string ] $CertificateFilePath = " $PWD \PowerShell.cer " ,
2016-06-07 00:54:25 +08:00
#Path to save generated pvk file
[ ValidateNotNullOrEmpty ( ) ]
2016-08-19 06:42:42 +08:00
[ string ] $PvkFilePath = " $env:Temp \PowerShell.pvk "
2016-06-07 00:54:25 +08:00
)
$makecertBinPath = " $ {env:ProgramFiles(x86)}\Windows Kits\10\bin\x64\MakeCert.exe "
2016-08-19 06:42:42 +08:00
Write-Verbose " Windows 10 SDK needed - https://go.microsoft.com/fwlink/p/?LinkID=822845 - Ensure MakeCert.exe is present @ $makecertBinPath "
2016-06-07 00:54:25 +08:00
if ( -not ( Test-Path $makecertBinPath ) )
{
throw " $makecertBinPath is required to generate a self-signed certificate "
}
Remove-Item $CertificateFilePath -Force -ErrorAction Ignore
Remove-Item $PvkFilePath -Force -ErrorAction Ignore
& $makecertBinPath -r -h 0 -n " CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US " -eku 1.3 . 6 . 1 . 5 . 5 . 7 . 3 . 3 -pe -sv $PvkFilePath $CertificateFilePath | Write-Verbose
2017-01-17 05:31:14 +08:00
2016-06-07 00:54:25 +08:00
Write-Verbose " Self-Signed Cert generated @ $CertificateFilePath "
return $CertificateFilePath
}
# Convert private pvk file format to pfx format to be consumed by signtool.exe
function ConvertTo-Pfx
{
[ CmdletBinding ( ) ]
param (
2017-01-17 05:31:14 +08:00
2016-06-07 00:54:25 +08:00
#Path to Certificate file
[ ValidateNotNullOrEmpty ( ) ]
2020-01-14 03:24:10 +08:00
[ string ] $CertificateFilePath = " $PWD \PowerShell.cer " ,
2016-06-07 00:54:25 +08:00
#Path to pvk file
[ ValidateNotNullOrEmpty ( ) ]
2016-08-19 06:42:42 +08:00
[ string ] $PvkFilePath = " $env:Temp \PowerShell.pvk " ,
2016-06-07 00:54:25 +08:00
#Path to generated pfx file
[ ValidateNotNullOrEmpty ( ) ]
2016-08-19 06:42:42 +08:00
[ string ] $PfxFilePath = " $env:Temp \PowerShell.pfx "
2016-06-07 00:54:25 +08:00
)
$pvk2pfxBinPath = " $ {env:ProgramFiles(x86)}\Windows Kits\10\bin\x64\pvk2pfx.exe "
2016-08-19 06:42:42 +08:00
Write-Verbose " Windows 10 SDK needed - https://go.microsoft.com/fwlink/p/?LinkID=822845 - Ensure pvk2pfx.exe is present @ $pvk2pfxBinPath "
2016-06-07 00:54:25 +08:00
if ( -not ( Test-Path $pvk2pfxBinPath ) )
{
2016-08-19 06:42:42 +08:00
throw " $pvk2pfxBinPath is required to convert pvk file to pfx file - one of the prerequisites to sign a package! "
2016-06-07 00:54:25 +08:00
}
2017-01-17 05:31:14 +08:00
2016-06-07 00:54:25 +08:00
Remove-Item $PfxFilePath -Force -ErrorAction Ignore
& $pvk2pfxBinPath / pvk $PvkFilePath / spc $CertificateFilePath / pfx $PfxFilePath / f | Write-Verbose
Write-Verbose " Pfx file generated @ $PfxFilePath "
return $PfxFilePath
}
# Sign a given package
2017-01-17 05:31:14 +08:00
# this function needs the proprietary pfx file
2016-06-07 00:54:25 +08:00
function Sign-Package
{
[ CmdletBinding ( ) ]
2017-01-17 05:31:14 +08:00
param (
#Path to package - Ex: PowerShell.msi, PowerShell.appx
[ Parameter ( Mandatory = $true ) ]
2016-06-07 00:54:25 +08:00
[ ValidateNotNullOrEmpty ( ) ]
[ string ] $PackageFilePath ,
2017-01-17 05:31:14 +08:00
2016-08-19 06:42:42 +08:00
#Path to generated pfx file to sign the package
2016-06-07 00:54:25 +08:00
[ ValidateNotNullOrEmpty ( ) ]
2016-08-19 06:42:42 +08:00
[ string ] $PfxFilePath = " $env:Temp \PowerShell.pfx "
2016-06-07 00:54:25 +08:00
)
$signtoolBinPath = " $ {env:ProgramFiles(x86)}\Windows Kits\10\bin\x64\SignTool.exe "
2016-08-19 06:42:42 +08:00
Write-Verbose " Windows 10 SDK needed - https://go.microsoft.com/fwlink/p/?LinkID=822845 - Ensure SignTool.exe is present @ $signtoolBinPath "
2016-06-07 00:54:25 +08:00
if ( -not ( Test-Path $signtoolBinPath ) )
{
throw " $signtoolBinPath is required to sign the package! "
}
& $signtoolBinPath sign -f $PfxFilePath -fd SHA256 -v $PackageFilePath | Write-Verbose
Write-Verbose " Authenticode signing successful for $PackageFilePath "
return $PackageFilePath
}
$certificate = New-SelfSignedCertificate -Verbose
ConvertTo-Pfx -Verbose
$signedPackage = Sign-Package -PackageFilePath $PackageFilePath -Verbose
Write-Output " Signed Package is available @ `' $signedPackage `' "
Write-Output " On Windows Full SKU - Import the self-signed certificate `' $certificate `' to TrustedStore (Import-Certificate) prior to installing the package "
2016-08-19 06:42:42 +08:00
Write-Output " On Windows Nano - Use `' $env:Windir \System32\Certoc.exe -AddStore TrustedPeople <Certificate> `' to import the self-signed certificate `' $certificate `' to TrustedStore "