2016-08-18 15:42:42 -07:00
# Utility to generate a self-signed certificate and sign a given package such as PowerShell.zip/appx/msi
2016-06-06 09:54:25 -07:00
[ CmdletBinding ()]
param (
2016-08-18 15:42:42 -07:00
#Path to package - Ex: PowerShell.msi, PowerShell.appx
2016-06-06 09:54:25 -07:00
[ Parameter ( Mandatory = $true )]
[ 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 (
#Path to save generated Certificate
[ ValidateNotNullOrEmpty ()]
2016-08-18 15:42:42 -07:00
[ string ] $CertificateFilePath = " $pwd \PowerShell.cer" ,
2016-06-06 09:54:25 -07:00
#Path to save generated pvk file
[ ValidateNotNullOrEmpty ()]
2016-08-18 15:42:42 -07:00
[ string ] $PvkFilePath = " $env:Temp \PowerShell.pvk"
2016-06-06 09:54:25 -07:00
)
$makecertBinPath = "${env:ProgramFiles(x86)}\Windows Kits\10\bin\x64\MakeCert.exe"
2016-08-18 15:42:42 -07:00
Write-Verbose "Windows 10 SDK needed - https://go.microsoft.com/fwlink/p/?LinkID=822845 - Ensure MakeCert.exe is present @ $makecertBinPath "
2016-06-06 09:54:25 -07: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
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 (
#Path to Certificate file
[ ValidateNotNullOrEmpty ()]
2016-08-18 15:42:42 -07:00
[ string ] $CertificateFilePath = " $pwd \PowerShell.cer" ,
2016-06-06 09:54:25 -07:00
#Path to pvk file
[ ValidateNotNullOrEmpty ()]
2016-08-18 15:42:42 -07:00
[ string ] $PvkFilePath = " $env:Temp \PowerShell.pvk" ,
2016-06-06 09:54:25 -07:00
#Path to generated pfx file
[ ValidateNotNullOrEmpty ()]
2016-08-18 15:42:42 -07:00
[ string ] $PfxFilePath = " $env:Temp \PowerShell.pfx"
2016-06-06 09:54:25 -07:00
)
$pvk2pfxBinPath = "${env:ProgramFiles(x86)}\Windows Kits\10\bin\x64\pvk2pfx.exe"
2016-08-18 15:42:42 -07:00
Write-Verbose "Windows 10 SDK needed - https://go.microsoft.com/fwlink/p/?LinkID=822845 - Ensure pvk2pfx.exe is present @ $pvk2pfxBinPath "
2016-06-06 09:54:25 -07:00
if ( -not ( Test-Path $pvk2pfxBinPath ))
{
2016-08-18 15:42:42 -07:00
throw " $pvk2pfxBinPath is required to convert pvk file to pfx file - one of the prerequisites to sign a package!"
2016-06-06 09:54:25 -07: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
# this function needs the proprietary pfx file
function Sign-Package
{
[ CmdletBinding ()]
param (
2016-08-18 15:42:42 -07:00
#Path to package - Ex: PowerShell.msi, PowerShell.appx
2016-06-06 09:54:25 -07:00
[ Parameter ( Mandatory = $true )]
[ ValidateNotNullOrEmpty ()]
[ string ] $PackageFilePath ,
2016-08-18 15:42:42 -07:00
#Path to generated pfx file to sign the package
2016-06-06 09:54:25 -07:00
[ ValidateNotNullOrEmpty ()]
2016-08-18 15:42:42 -07:00
[ string ] $PfxFilePath = " $env:Temp \PowerShell.pfx"
2016-06-06 09:54:25 -07:00
)
$signtoolBinPath = "${env:ProgramFiles(x86)}\Windows Kits\10\bin\x64\SignTool.exe"
2016-08-18 15:42:42 -07:00
Write-Verbose "Windows 10 SDK needed - https://go.microsoft.com/fwlink/p/?LinkID=822845 - Ensure SignTool.exe is present @ $signtoolBinPath "
2016-06-06 09:54:25 -07: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-18 15:42:42 -07:00
Write-Output "On Windows Nano - Use `' $env:Windir \System32\Certoc.exe -AddStore TrustedPeople <Certificate> `' to import the self-signed certificate `' $certificate `' to TrustedStore"