@@ -20,3 +20,151 @@ Describe "Windows platform file signatures" -Tags 'Feature' {
2020 $signature.SignatureType | Should - BeExactly ' Catalog'
2121 }
2222}
23+
24+ Describe " Windows file content signatures" - Tags @ (' Feature' , ' RequireAdminOnWindows' ) {
25+ $PSDefaultParameterValues = @ { " It:Skip" = (-not $IsWindows ) }
26+
27+ BeforeAll {
28+ $session = New-PSSession - UseWindowsPowerShell
29+ try {
30+ # New-SelfSignedCertificate runs in implicit remoting so do all the
31+ # setup work over there
32+ $caRootThumbprint , $signingThumbprint = Invoke-Command - Session $session - ScriptBlock {
33+ $testPrefix = ' SelfSignedTest'
34+
35+ $enhancedKeyUsage = [Security.Cryptography.OidCollection ]::new()
36+ $null = $enhancedKeyUsage.Add (' 1.3.6.1.5.5.7.3.3' ) # Code Signing
37+
38+ $caParams = @ {
39+ Extension = @ (
40+ [Security.Cryptography.X509Certificates.X509BasicConstraintsExtension ]::new($true , $false , 0 , $true ),
41+ [Security.Cryptography.X509Certificates.X509KeyUsageExtension ]::new(' KeyCertSign' , $false ),
42+ [Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension ]::new($enhancedKeyUsage , $false )
43+ )
44+ CertStoreLocation = ' Cert:\CurrentUser\My'
45+ NotAfter = (Get-Date ).AddDays(1 )
46+ Type = ' Custom'
47+ }
48+ $caRoot = PKI\New-SelfSignedCertificate @caParams - Subject " CN=$testPrefix -CA"
49+
50+ $rootStore = Get-Item - Path Cert:\LocalMachine\Root
51+ $rootStore.Open ([System.Security.Cryptography.X509Certificates.OpenFlags ]::ReadWrite)
52+ try {
53+ $rootStore.Add ([System.Security.Cryptography.X509Certificates.X509Certificate2 ]::new($caRoot.RawData ))
54+ } finally {
55+ $rootStore.Close ()
56+ }
57+
58+ $certParams = @ {
59+ CertStoreLocation = ' Cert:\CurrentUser\My'
60+ KeyUsage = ' DigitalSignature'
61+ TextExtension = @ (" 2.5.29.37={text}1.3.6.1.5.5.7.3.3" , " 2.5.29.19={text}" )
62+ Type = ' Custom'
63+ }
64+ $certificate = PKI\New-SelfSignedCertificate @certParams - Subject " CN=$testPrefix -Signed" - Signer $caRoot
65+
66+ $publisherStore = Get-Item - Path Cert:\LocalMachine\TrustedPublisher
67+ $publisherStore.Open ([System.Security.Cryptography.X509Certificates.OpenFlags ]::ReadWrite)
68+ try {
69+ $publisherStore.Add ([System.Security.Cryptography.X509Certificates.X509Certificate2 ]::new($certificate.RawData ))
70+ } finally {
71+ $publisherStore.Close ()
72+ }
73+
74+ $caRoot | Remove-Item
75+
76+ $caRoot.Thumbprint , $certificate.Thumbprint
77+ }
78+ } finally {
79+ $session | Remove-PSSession
80+ }
81+
82+ $certificate = Get-Item - Path Cert:\CurrentUser\My\$signingThumbprint
83+ }
84+
85+ AfterAll {
86+ Remove-Item - Path Cert:\LocalMachine\Root\$caRootThumbprint - Force
87+ Remove-Item - Path Cert:\LocalMachine\TrustedPublisher\$signingThumbprint - Force
88+ Remove-Item - Path Cert:\CurrentUser\My\$signingThumbprint - Force
89+ }
90+
91+ It " Validates signature using path on even char count with Encoding <Encoding>" - TestCases @ (
92+ @ { Encoding = ' ASCII' }
93+ @ { Encoding = ' Unicode' }
94+ @ { Encoding = ' UTF8BOM' }
95+ @ { Encoding = ' UTF8NoBOM' }
96+ ) {
97+ param ($Encoding )
98+
99+ Set-Content - Path testdrive:\test.ps1 - Value ' Write-Output "Hello World"' - Encoding $Encoding
100+
101+ $scriptPath = Join-Path $TestDrive test.ps1
102+ $status = Set-AuthenticodeSignature - FilePath $scriptPath - Certificate $certificate
103+ $status.Status | Should - Be ' Valid'
104+
105+ $actual = Get-AuthenticodeSignature - FilePath $scriptPath
106+ $actual.SignerCertificate.Thumbprint | Should - Be $certificate.Thumbprint
107+ $actual.Status | Should - Be ' Valid'
108+ }
109+
110+ It " Validates signature using path on odd char count with Encoding <Encoding>" - TestCases @ (
111+ @ { Encoding = ' ASCII' }
112+ @ { Encoding = ' Unicode' }
113+ @ { Encoding = ' UTF8BOM' }
114+ @ { Encoding = ' UTF8NoBOM' }
115+ ) {
116+ param ($Encoding )
117+
118+ Set-Content - Path testdrive:\test.ps1 - Value ' Write-Output "Hello World!"' - Encoding $Encoding
119+
120+ $scriptPath = Join-Path $TestDrive test.ps1
121+ $status = Set-AuthenticodeSignature - FilePath $scriptPath - Certificate $certificate
122+ $status.Status | Should - Be ' Valid'
123+
124+ $actual = Get-AuthenticodeSignature - FilePath $scriptPath
125+ $actual.SignerCertificate.Thumbprint | Should - Be $certificate.Thumbprint
126+ $actual.Status | Should - Be ' Valid'
127+ }
128+
129+ It " Validates signature using content on even char count with Encoding <Encoding>" - TestCases @ (
130+ @ { Encoding = ' ASCII' }
131+ @ { Encoding = ' Unicode' }
132+ @ { Encoding = ' UTF8BOM' }
133+ @ { Encoding = ' UTF8NoBOM' }
134+ ) {
135+ param ($Encoding )
136+
137+ Set-Content - Path testdrive:\test.ps1 - Value ' Write-Output "Hello World"' - Encoding $Encoding
138+
139+ $scriptPath = Join-Path $TestDrive test.ps1
140+ $status = Set-AuthenticodeSignature - FilePath $scriptPath - Certificate $certificate
141+ $status.Status | Should - Be ' Valid'
142+
143+ $fileBytes = Get-Content - Path testdrive:\test.ps1 - AsByteStream
144+
145+ $actual = Get-AuthenticodeSignature - Content $fileBytes - SourcePathOrExtension .ps1
146+ $actual.SignerCertificate.Thumbprint | Should - Be $certificate.Thumbprint
147+ $actual.Status | Should - Be ' Valid'
148+ }
149+
150+ It " Validates signature using content on odd char count with Encoding <Encoding>" - TestCases @ (
151+ @ { Encoding = ' ASCII' }
152+ @ { Encoding = ' Unicode' }
153+ @ { Encoding = ' UTF8BOM' }
154+ @ { Encoding = ' UTF8NoBOM' }
155+ ) {
156+ param ($Encoding )
157+
158+ Set-Content - Path testdrive:\test.ps1 - Value ' Write-Output "Hello World!"' - Encoding $Encoding
159+
160+ $scriptPath = Join-Path $TestDrive test.ps1
161+ $status = Set-AuthenticodeSignature - FilePath $scriptPath - Certificate $certificate
162+ $status.Status | Should - Be ' Valid'
163+
164+ $fileBytes = Get-Content - Path testdrive:\test.ps1 - AsByteStream
165+
166+ $actual = Get-AuthenticodeSignature - Content $fileBytes - SourcePathOrExtension .ps1
167+ $actual.SignerCertificate.Thumbprint | Should - Be $certificate.Thumbprint
168+ $actual.Status | Should - Be ' Valid'
169+ }
170+ }
0 commit comments