@@ -20,3 +20,151 @@ Describe "Windows platform file signatures" -Tags 'Feature' {
20
20
$signature.SignatureType | Should - BeExactly ' Catalog'
21
21
}
22
22
}
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