@@ -59,26 +59,48 @@ function Test-RequiredAssets {
59
59
[Parameter (Mandatory = $true )]
60
60
[string ]$WorkingDirectory ,
61
61
62
- [Parameter (Mandatory = $true )]
62
+ [Parameter (Mandatory = $false )]
63
63
[string ]$NuGetPackagesZip ,
64
64
65
- [Parameter (Mandatory = $true )]
66
- [string ]$SymbolsPackagesZip
65
+ [Parameter (Mandatory = $false )]
66
+ [string ]$SymbolsPackagesZip ,
67
+
68
+ [Parameter (Mandatory = $false )]
69
+ [string ]$NativeShimsZip
67
70
)
68
71
69
72
Write-Host " `n Validating required build assets..."
70
- $requiredFiles = @ {
71
- $NuGetPackagesZip = " NuGet packages"
72
- $SymbolsPackagesZip = " Symbol packages"
73
- }
74
73
75
- foreach ($required in $requiredFiles.GetEnumerator ()) {
76
- $found = Get-ChildItem - Path $WorkingDirectory - Filter $required.Key - ErrorAction SilentlyContinue
77
- if (-not $found ) {
78
- throw " Required build asset not found: $ ( $required.Key ) `n This file should contain $ ( $required.Value ) "
74
+ $hasCorePackages = -not [string ]::IsNullOrWhiteSpace($NuGetPackagesZip ) -and -not [string ]::IsNullOrWhiteSpace($SymbolsPackagesZip )
75
+ $hasNativeShims = -not [string ]::IsNullOrWhiteSpace($NativeShimsZip )
76
+
77
+ if (-not $hasCorePackages -and -not $hasNativeShims ) {
78
+ throw " No package files specified. Please provide either core packages or native shims package paths."
79
+ }
80
+
81
+ if ($hasCorePackages ) {
82
+ Write-Host " 🔍 Validating core packages..." - ForegroundColor Cyan
83
+ $coreFiles = @ {
84
+ $NuGetPackagesZip = " NuGet packages"
85
+ $SymbolsPackagesZip = " Symbol packages"
86
+ }
87
+
88
+ foreach ($required in $coreFiles.GetEnumerator ()) {
89
+ $found = Get-ChildItem - Path $WorkingDirectory - Filter $required.Key - ErrorAction SilentlyContinue
90
+ if (-not $found ) {
91
+ throw " Required build asset not found: $ ( $required.Key ) `n This file should contain $ ( $required.Value ) "
92
+ }
93
+ Write-Host " ✅ Found $ ( $required.Value ) in: $ ( $found.Name ) " - ForegroundColor Green
79
94
}
95
+ }
80
96
81
- Write-Host " ✅ Found $ ( $required.Value ) in: $ ( $found.Name ) " - ForegroundColor Green
97
+ if ($hasNativeShims ) {
98
+ Write-Host " 🔍 Validating native shims package..." - ForegroundColor Cyan
99
+ $found = Get-ChildItem - Path $WorkingDirectory - Filter $NativeShimsZip - ErrorAction SilentlyContinue
100
+ if (-not $found ) {
101
+ throw " Required native shims asset not found: $NativeShimsZip "
102
+ }
103
+ Write-Host " ✅ Found Native Shims package in: $ ( $found.Name ) " - ForegroundColor Green
82
104
}
83
105
}
84
106
@@ -110,6 +132,86 @@ function Initialize-DirectoryStructure {
110
132
return $directories
111
133
}
112
134
135
+ function Process-ZipPackage {
136
+ [CmdletBinding ()]
137
+ param (
138
+ [Parameter (Mandatory = $true )]
139
+ [string ]$ZipFile ,
140
+
141
+ [Parameter (Mandatory = $true )]
142
+ [hashtable ]$Directories ,
143
+
144
+ [Parameter (Mandatory = $true )]
145
+ [string ]$SignToolPath ,
146
+
147
+ [Parameter (Mandatory = $true )]
148
+ [string ]$NuGetPath ,
149
+
150
+ [Parameter (Mandatory = $true )]
151
+ [string ]$Thumbprint ,
152
+
153
+ [Parameter (Mandatory = $true )]
154
+ [string ]$TimestampServer
155
+ )
156
+
157
+ Write-Host " `n 🔄 Processing: $ZipFile " - ForegroundColor Cyan
158
+
159
+ $extractPath = Join-Path $Directories.Unsigned ([System.IO.Path ]::GetFileNameWithoutExtension($ZipFile ))
160
+ Write-Host " 📂 Extracting to: $extractPath " - ForegroundColor Gray
161
+
162
+ $zipPath = Join-Path $Directories.WorkingDir $ZipFile
163
+ Expand-Archive - Path $zipPath - DestinationPath $extractPath - Force
164
+
165
+ Write-Host " 📋 Copying packages to unsigned directory" - ForegroundColor Gray
166
+ $packages = Get-ChildItem - Path $extractPath - Recurse - Include * .nupkg, * .snupkg
167
+ foreach ($package in $packages ) {
168
+ Write-Host " 📦 Copying: $ ( $package.Name ) "
169
+
170
+ # Verify GitHub attestation
171
+ if (-not (Test-GithubAttestation - FilePath $package.FullName - RepoName " Yubico/Yubico.NET.SDK" )) {
172
+ throw " Attestation verification failed for: $ ( $package.Name ) "
173
+ }
174
+
175
+ Copy-Item - Path $package.FullName - Destination $Directories.Unsigned - Force
176
+ }
177
+ Write-Host " ✅ Copied $ ( $packages.Count ) package(s)"
178
+
179
+ # Process the packages
180
+ $nugetPackages = Get-ChildItem - Path $Directories.Unsigned - Filter " *.nupkg"
181
+ foreach ($package in $nugetPackages ) {
182
+ Write-Host " `n 📝 Signing contents of: $ ( $package.Name ) " - ForegroundColor White
183
+
184
+ $extractPath = Join-Path $Directories.Libraries ([System.IO.Path ]::GetFileNameWithoutExtension($package.Name ))
185
+ Write-Host " 📂 Extracting to: $extractPath "
186
+ Expand-Archive - Path $package.FullName - DestinationPath $extractPath - Force
187
+
188
+ Write-Debug " 🧹 Cleaning package structure"
189
+ Get-ChildItem - Path $extractPath - Recurse - Include " _rels" , " package" | Remove-Item - Force - Recurse
190
+ Get-ChildItem - Path $extractPath - Recurse - Filter ' [Content_Types].xml' | Remove-Item - Force
191
+
192
+ Write-Host " ✍️ Signing assemblies..."
193
+ $dlls = Get-ChildItem - Path $extractPath - Include " *.dll" - Recurse
194
+ foreach ($dll in $dlls ) {
195
+ $frameworkDir = Split-Path (Split-Path $dll.FullName - Parent) - Leaf
196
+ $fileName = Split-Path $dll.FullName - Leaf
197
+ Write-Host " 🔏 Signing: ..\$frameworkDir \$fileName " - ForegroundColor Gray
198
+ Sign- SingleFile - FilePath $dll.FullName - Thumbprint $Thumbprint - SignToolPath $SignToolPath - TimestampServer $TimestampServer
199
+ }
200
+
201
+ Write-Host " 📦 Repacking assemblies..." - ForegroundColor White
202
+ Get-ChildItem - Path $extractPath - Recurse - Filter " *.nuspec" |
203
+ ForEach-Object {
204
+ Write-Host " 📥 Packing: $ ( $_.Name ) "
205
+ $output = & $NuGetPath pack $_.FullName - OutputDirectory $Directories.Packages 2>&1
206
+
207
+ if ($LASTEXITCODE -ne 0 ) {
208
+ $output | ForEach-Object { Write-Host $_ }
209
+ throw " Packing failed for file: $ ( $_.FullName ) "
210
+ }
211
+ }
212
+ }
213
+ }
214
+
113
215
function Test-GithubAttestation {
114
216
[CmdletBinding ()]
115
217
param (
@@ -120,23 +222,21 @@ function Test-GithubAttestation {
120
222
[string ]$RepoName
121
223
)
122
224
123
- # Get the parent directory name and the file name
124
225
$fileName = (Get-ChildItem $FilePath ).Name
125
-
126
- Write-Host " 🔐 Verifying attestation for: ..$parentDir \$fileName " - ForegroundColor Gray
226
+ Write-Host " 🔐 Verifying attestation for: $fileName " - ForegroundColor Gray
127
227
128
228
try {
129
229
$output = gh attestation verify $FilePath -- repo $RepoName 2>&1
130
230
if ($LASTEXITCODE -ne 0 ) {
131
231
Write-Host $output - ForegroundColor Red
132
- throw $output # This will trigger the catch block
232
+ throw $output
133
233
}
134
234
135
- Write-Host " ✅ Verified" - ForegroundColor Green
235
+ Write-Host " ✅ Verified" - ForegroundColor Green
136
236
return $true
137
237
}
138
238
catch {
139
- Write-Host " ❌ Verification failed: $_ " - ForegroundColor Red
239
+ Write-Host " ❌ Verification failed: $_ " - ForegroundColor Red
140
240
return $false
141
241
}
142
242
}
@@ -146,17 +246,20 @@ function Test-GithubAttestation {
146
246
Signs NuGet and Symbol packages using a smart card certificate.
147
247
148
248
. DESCRIPTION
149
- Signs NuGet packages (*.nupkg) and their corresponding symbol packages (*.snupkg) using a hardware-based certificate.
150
- The script processes the contents of two required zip files ('Nuget Packages.zip' and 'Symbols Packages.zip'),
151
- signs all assemblies within the NuGet packages, repacks them, and then signs both the NuGet and Symbol packages.
249
+ Signs NuGet packages (*.nupkg), corresponding symbol packages (*.snupkg), and optionally native shim packages
250
+ using a hardware-based certificate. The script can process:
251
+ 1. Core packages (NuGet and Symbol packages)
252
+ 2. Native shims package
253
+ 3. Both core packages and native shims
254
+
255
+ The script signs all assemblies within the packages, repacks them, and then signs the final packages.
152
256
153
257
How to use:
154
258
1. Create a release folder on your machine e.g. ../releases/1.12
155
- 2. Download the build assets "Nuget Packages.zip" and "Symbols Packages.zip" from the latest SDK build action
156
- to the newly created folder.
157
- 3. Start a Powershell terminal, and load the script by running the following command:
259
+ 2. Download the build assets from the latest SDK build action to the newly created folder
260
+ 3. Start a Powershell terminal, and load the script:
158
261
> . \.Yubico.NET.SDK\build\sign.ps1
159
- 4. The script can be invoked by following the examples below.
262
+ 4. Follow the examples below to sign packages
160
263
161
264
Set $DebugPreference = "Continue" for verbose output
162
265
@@ -176,19 +279,28 @@ Optional. Path to nuget.exe. Defaults to "nuget.exe" (expects it in PATH).
176
279
Optional. URL of the timestamp server. Defaults to "http://timestamp.digicert.com".
177
280
178
281
. PARAMETER NuGetPackagesZip
179
- Optional. Name of the NuGet packages zip file. Defaults to "Nuget Packages.zip" .
282
+ Optional. Name of the NuGet packages zip file. Required if signing core packages .
180
283
181
284
. PARAMETER SymbolsPackagesZip
182
- Optional. Name of the symbols packages zip file. Defaults to "Symbols Packages.zip".
285
+ Optional. Name of the symbols packages zip file. Required if signing core packages.
286
+
287
+ . PARAMETER NativeShimsZip
288
+ Optional. Name of the native shims package zip file.
183
289
184
290
. PARAMETER CleanWorkingDirectory
185
291
Optional switch. If specified, cleans the working directories before processing.
186
292
187
293
. EXAMPLE
188
- Invoke-NuGetPackageSigning -Thumbprint "0123456789ABCDEF" -WorkingDirectory "C:\Signing"
294
+ # Sign only native shims
295
+ Invoke-NuGetPackageSigning -Thumbprint "0123456789ABCDEF" -WorkingDirectory "C:\Signing" -NativeShimsZip "Yubico.NativeShims.nupkg.zip"
296
+
297
+ . EXAMPLE
298
+ # Sign core packages
299
+ Invoke-NuGetPackageSigning -Thumbprint "0123456789ABCDEF" -WorkingDirectory "C:\Signing" -NuGetPackagesZip "Nuget Packages.zip" -SymbolsPackagesZip "Symbols Packages.zip"
189
300
190
301
. EXAMPLE
191
- Invoke-NuGetPackageSigning -Thumbprint "0123456789ABCDEF" -WorkingDirectory "C:\Signing" -CleanWorkingDirectory -NuGetPath "C:\Tools\nuget.exe"
302
+ # Sign both core packages and native shims
303
+ Invoke-NuGetPackageSigning -Thumbprint "0123456789ABCDEF" -WorkingDirectory "C:\Signing" -NuGetPackagesZip "Nuget Packages.zip" -SymbolsPackagesZip "Symbols Packages.zip" -NativeShimsZip "Yubico.NativeShims.nupkg.zip"
192
304
193
305
. NOTES
194
306
Requires:
@@ -217,10 +329,13 @@ function Invoke-NuGetPackageSigning {
217
329
[string ]$TimestampServer = " http://timestamp.digicert.com" ,
218
330
219
331
[Parameter (Mandatory = $false )]
220
- [string ]$NuGetPackagesZip = " Nuget Packages.zip " ,
332
+ [string ]$NuGetPackagesZip ,
221
333
222
334
[Parameter (Mandatory = $false )]
223
- [string ]$SymbolsPackagesZip = " Symbols Packages.zip" ,
335
+ [string ]$SymbolsPackagesZip ,
336
+
337
+ [Parameter (Mandatory = $false )]
338
+ [string ]$NativeShimsZip ,
224
339
225
340
[Parameter (Mandatory = $false )]
226
341
[switch ]$CleanWorkingDirectory
@@ -244,7 +359,7 @@ function Invoke-NuGetPackageSigning {
244
359
if (-not (Get-Command gh - ErrorAction SilentlyContinue)) {
245
360
throw " GitHub CLI installed or not found in PATH"
246
361
}
247
- Write-Host " ✓ GitHub CLI found at: $NuGetPath "
362
+ Write-Host " ✓ GitHub CLI found"
248
363
249
364
# Verify certificate is available and log details
250
365
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Thumbprint -eq $Thumbprint }
@@ -272,76 +387,32 @@ function Invoke-NuGetPackageSigning {
272
387
$directories = Initialize-DirectoryStructure - BaseDirectory $WorkingDirectory
273
388
274
389
# Validate required zip files
275
- Test-RequiredAssets - WorkingDirectory $WorkingDirectory - NuGetPackagesZip $NuGetPackagesZip - SymbolsPackagesZip $SymbolsPackagesZip
276
-
277
- # Process each zip file
278
- Write-Host " `n 📦 Processing ZIP files..." - ForegroundColor Yellow
279
- $zipFiles = Get-ChildItem - Path $WorkingDirectory - Filter " *.zip"
280
- foreach ($zip in $zipFiles ) {
281
- Write-Host " `n 🔄 Processing: $ ( $zip.Name ) " - ForegroundColor Cyan
282
-
283
- $extractPath = Join-Path $directories.Unsigned ([System.IO.Path ]::GetFileNameWithoutExtension($zip.Name ))
284
- Write-Host " 📂 Extracting to: $extractPath " - ForegroundColor Gray
285
- Expand-Archive - Path $zip.FullName - DestinationPath $extractPath - Force
286
-
287
- Write-Host " 📋 Copying packages to unsigned directory" - ForegroundColor Gray
288
- $packages = Get-ChildItem - Path $extractPath - Recurse - Include * .nupkg, * .snupkg
289
- foreach ($package in $packages ) {
290
- Write-Host " Copying: $ ( $package.Name ) "
390
+ Test-RequiredAssets - WorkingDirectory $WorkingDirectory - NuGetPackagesZip $NuGetPackagesZip - SymbolsPackagesZip $SymbolsPackagesZip - NativeShimsZip $NativeShimsZip
291
391
292
- # Verify GitHub attestation (that the file has been downloaded from our repo)
293
- if (-not (Test-GithubAttestation - FilePath $package.FullName - RepoName " Yubico/Yubico.NET.SDK" )) {
294
- throw " Attestation verification failed for: $ ( $package.Name ) "
295
- }
392
+ # Determine which packages to process
393
+ $hasCorePackages = -not [string ]::IsNullOrWhiteSpace($NuGetPackagesZip ) -and -not [string ]::IsNullOrWhiteSpace($SymbolsPackagesZip )
394
+ $hasNativeShims = -not [string ]::IsNullOrWhiteSpace($NativeShimsZip )
296
395
297
- Copy-Item - Path $package.FullName - Destination $directories.Unsigned - Force
298
- }
299
- Write-Host " ✓ Copied $ ( $packages.Count ) package(s)"
300
- }
396
+ # Process packages based on what was provided
397
+ if ($hasCorePackages ) {
398
+ Write-Host " `n 📦 Processing Core Packages..." - ForegroundColor Yellow
399
+ # Process core packages
400
+ Process - ZipPackage - ZipFile $NuGetPackagesZip - Directories $directories - SignToolPath $SignToolPath - NuGetPath $NuGetPath - Thumbprint $Thumbprint - TimestampServer $TimestampServer
301
401
302
- # First process nupkg files to sign their contents
303
- Write-Host " `n 📦 Processing NuGet packages..." - ForegroundColor Yellow
304
- $nugetPackages = Get-ChildItem - Path $directories.Unsigned - Filter " *.nupkg"
305
- foreach ($package in $nugetPackages ) {
306
- Write-Host " `n Signing contents of: $ ( $package.Name ) "
402
+ Write-Host " `n 📦 Copying Symbol Packages..." - ForegroundColor Yellow
403
+ $symbolsExtractPath = Join-Path $directories.Unsigned ([System.IO.Path ]::GetFileNameWithoutExtension($SymbolsPackagesZip ))
404
+ Expand-Archive - Path (Join-Path $WorkingDirectory $SymbolsPackagesZip ) - DestinationPath $symbolsExtractPath - Force
307
405
308
- $extractPath = Join-Path $directories.Libraries ([System.IO.Path ]::GetFileNameWithoutExtension($package.Name ))
309
- Write-Host " Extracting to: $extractPath "
310
- Expand-Archive - Path $package.FullName - DestinationPath $extractPath - Force
311
-
312
- Write-Debug " Cleaning package structure"
313
- Get-ChildItem - Path $extractPath - Recurse - Include " _rels" , " package" | Remove-Item - Force - Recurse
314
- Get-ChildItem - Path $extractPath - Recurse - Filter ' [Content_Types].xml' | Remove-Item - Force
315
-
316
- Write-Host " Signing assemblies..."
317
- $dlls = Get-ChildItem - Path $extractPath - Include " *.dll" - Recurse
318
- foreach ($dll in $dlls ) {
319
- # Get the parent directory name (framework target) and the file name
320
- $frameworkDir = Split-Path (Split-Path $dll.FullName - Parent) - Leaf
321
- $fileName = Split-Path $dll.FullName - Leaf
322
- Write-Host " ✍️ Signing: ..\$frameworkDir \$fileName " - ForegroundColor Gray
323
- Sign- SingleFile - FilePath $dll.FullName - Thumbprint $Thumbprint - SignToolPath $SignToolPath - TimestampServer $TimestampServer
324
- }
325
-
326
- Write-Host " Repacking assemblies..."
327
- Get-ChildItem - Path $extractPath - Recurse - Filter " *.nuspec" |
328
- ForEach-Object {
329
- Write-Host " Packing: $ ( $_.Name ) "
330
- $output = & $NuGetPath pack $_.FullName - OutputDirectory $directories.Packages 2>&1
331
-
332
- if ($LASTEXITCODE -ne 0 ) {
333
- $output | ForEach-Object { Write-Host $_ }
334
- throw " Signing failed for file: $FilePath "
335
- }
406
+ $symbolPackages = Get-ChildItem - Path $symbolsExtractPath - Recurse - Filter " *.snupkg"
407
+ foreach ($package in $symbolPackages ) {
408
+ Write-Host " Copying: $ ( $package.Name ) "
409
+ Copy-Item - Path $package.FullName - Destination $directories.Packages - Force
336
410
}
337
411
}
338
412
339
- # Copy symbol packages to output directory
340
- Write-Host " `n Copying symbol packages..." - ForegroundColor Yellow
341
- $symbolPackages = Get-ChildItem - Path $directories.Unsigned - Filter " *.snupkg"
342
- foreach ($package in $symbolPackages ) {
343
- Write-Host " Copying: $ ( $package.Name ) "
344
- Copy-Item - Path $package.FullName - Destination $directories.Packages - Force
413
+ if ($hasNativeShims ) {
414
+ Write-Host " `n 🔧 Processing Native Shims Package..." - ForegroundColor Yellow
415
+ Process - ZipPackage - ZipFile $NativeShimsZip - Directories $directories - SignToolPath $SignToolPath - NuGetPath $NuGetPath - Thumbprint $Thumbprint - TimestampServer $TimestampServer
345
416
}
346
417
347
418
# Sign all final packages (both nupkg and snupkg)
0 commit comments