Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
version:
description: Release version to build/publish (for example 0.3.0)
description: Release version to build/publish (for example 0.5.0)
required: true
type: string
publish_nuget:
Expand Down
18 changes: 9 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ repository = "https://github.com/Devolutions/psign"

[package]
name = "psign"
version = "0.4.0"
version = "0.5.0"
edition = "2024"
description = "Rust port of the Windows SDK signtool.exe (Authenticode sign/verify/timestamp) with portable digest helpers."
license.workspace = true
Expand Down
4 changes: 3 additions & 1 deletion PowerShell/Devolutions.Psign/Devolutions.Psign.psd1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@{
RootModule = 'Devolutions.Psign.psm1'
ModuleVersion = '0.4.0'
ModuleVersion = '0.5.0'
GUID = 'e6e50e4b-bf25-4ed6-a343-49f904e79f8f'
Author = 'Devolutions'
CompanyName = 'Devolutions'
Expand All @@ -12,7 +12,9 @@
FormatsToProcess = @('Devolutions.Psign.Format.ps1xml')
CmdletsToExport = @(
'Get-PsignSignature',
'New-PsignFileCatalog',
'Set-PsignSignature',
'Test-PsignFileCatalog',
'Test-PsignModule',
'Protect-PsignModule',
'Unprotect-PsignSignature'
Expand Down
7 changes: 7 additions & 0 deletions PowerShell/Devolutions.Psign/Devolutions.Psign.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,10 @@ Register-ArgumentCompleter -CommandName Test-PsignModule -ParameterName Policy -
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}

Register-ArgumentCompleter -CommandName New-PsignFileCatalog -ParameterName CatalogVersion -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
@('1', '2') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
91 changes: 91 additions & 0 deletions PowerShell/tests/PsignFileCatalog.Cmdlets.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
Set-StrictMode -Version Latest

function script:Ensure-PsignModule {
Remove-Module Devolutions.Psign -Force -ErrorAction SilentlyContinue
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$modulePath = Join-Path (Join-Path $repoRoot 'PowerShell\Devolutions.Psign') 'Devolutions.Psign.psd1'
Import-Module $modulePath -Force
}

Describe 'Portable file catalog cmdlets' {
BeforeAll {
Ensure-PsignModule
$script:TempRoot = Join-Path ([System.IO.Path]::GetTempPath()) "psign-catalog-$([System.Guid]::NewGuid().ToString('N'))"
New-Item -ItemType Directory -Force -Path $script:TempRoot | Out-Null
}

AfterAll {
if ($script:TempRoot) {
Remove-Item -LiteralPath $script:TempRoot -Recurse -Force -ErrorAction SilentlyContinue
}
}

BeforeEach {
$script:CaseRoot = Join-Path $script:TempRoot ([System.Guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Force -Path $script:CaseRoot | Out-Null
}

It 'creates and validates a recursive SHA256 catalog' {
New-Item -ItemType Directory -Force -Path (Join-Path $script:CaseRoot 'sub') | Out-Null
Set-Content -LiteralPath (Join-Path $script:CaseRoot 'a.txt') -Value 'alpha' -NoNewline -Encoding UTF8
Set-Content -LiteralPath (Join-Path $script:CaseRoot 'sub\b.txt') -Value 'bravo' -NoNewline -Encoding UTF8
$catalogPath = Join-Path $script:CaseRoot 'catalog.cat'

$created = New-PsignFileCatalog -Path $script:CaseRoot -CatalogFilePath $catalogPath
$created | Should -BeOfType ([System.IO.FileInfo])
$created.Exists | Should -BeTrue

Test-PsignFileCatalog -CatalogFilePath $catalogPath -Path $script:CaseRoot -SkipTrust | Should -Be 'Valid'

$detailed = Test-PsignFileCatalog -CatalogFilePath $catalogPath -Path $script:CaseRoot -SkipTrust -Detailed
$detailed.HashAlgorithm | Should -Be 'SHA256'
$detailed.CatalogItems.Path | Should -Contain 'a.txt'
$detailed.CatalogItems.Path | Should -Contain 'sub/b.txt'
$detailed.PathItems.Status | Should -Not -Contain 'HashMismatch'
$detailed.Signature.Status | Should -Be 'NotSigned'
}

It 'reports tampered files and honors FilesToSkip' {
Set-Content -LiteralPath (Join-Path $script:CaseRoot 'a.txt') -Value 'alpha' -NoNewline -Encoding UTF8
$catalogPath = Join-Path $script:CaseRoot 'catalog.cat'
New-PsignFileCatalog -Path $script:CaseRoot -CatalogFilePath $catalogPath | Out-Null
Set-Content -LiteralPath (Join-Path $script:CaseRoot 'a.txt') -Value 'tampered' -NoNewline -Encoding UTF8

Test-PsignFileCatalog -CatalogFilePath $catalogPath -Path $script:CaseRoot -SkipTrust | Should -Be 'ValidationFailed'
$detailed = Test-PsignFileCatalog -CatalogFilePath $catalogPath -Path $script:CaseRoot -SkipTrust -Detailed
($detailed.PathItems | Where-Object Path -EQ 'a.txt').Status | Should -Be 'HashMismatch'

Test-PsignFileCatalog -CatalogFilePath $catalogPath -Path $script:CaseRoot -SkipTrust -FilesToSkip 'a.txt' | Should -Be 'Valid'
}

It 'rejects duplicate filenames for multiple unrelated paths' {
$left = Join-Path $script:CaseRoot 'left'
$right = Join-Path $script:CaseRoot 'right'
New-Item -ItemType Directory -Force -Path $left, $right | Out-Null
Set-Content -LiteralPath (Join-Path $left 'same.txt') -Value 'left' -NoNewline -Encoding UTF8
Set-Content -LiteralPath (Join-Path $right 'same.txt') -Value 'right' -NoNewline -Encoding UTF8

{ New-PsignFileCatalog -Path $left, $right -CatalogFilePath (Join-Path $script:CaseRoot 'catalog.cat') -ErrorAction Stop } |
Should -Throw -ExpectedMessage '*duplicate subject file name*'
}

It 'supports WhatIf without creating a catalog' {
Set-Content -LiteralPath (Join-Path $script:CaseRoot 'a.txt') -Value 'alpha' -NoNewline -Encoding UTF8
$catalogPath = Join-Path $script:CaseRoot 'catalog.cat'

New-PsignFileCatalog -Path $script:CaseRoot -CatalogFilePath $catalogPath -WhatIf

Test-Path -LiteralPath $catalogPath | Should -BeFalse
}

It 'reports the embedded signature status for signed catalog fixtures' {
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$catalogPath = Join-Path $repoRoot 'tests\fixtures\generated-signed\catalog\sample.cat'
$memberPath = Join-Path $repoRoot 'tests\fixtures\generated-unsigned\catalog\member.sys'

$detailed = Test-PsignFileCatalog -CatalogFilePath $catalogPath -Path $memberPath -SkipTrust -Detailed

$detailed.Signature.Status | Should -Be 'Valid'
$detailed.Signature.SignatureType | Should -Be ([System.Management.Automation.SignatureType]::Catalog)
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ dotnet tool run psign-tool -- --help
Create local dotnet tool packages from prebuilt release artifacts:

```powershell
pwsh ./nuget/pack-psign-dotnet-tool.ps1 -Version 0.3.0 -ArtifactsRoot ./dist -OutputDir ./dist/nuget
pwsh ./nuget/pack-psign-dotnet-tool.ps1 -Version 0.5.0 -ArtifactsRoot ./dist -OutputDir ./dist/nuget
```

The package is built from native `psign-tool` artifacts for `win-x64`, `win-arm64`, `linux-x64`, `linux-arm64`, `osx-x64`, and `osx-arm64`, plus an `any` fallback package for unsupported runtimes.
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-authenticode-trust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-authenticode-trust"
version = "0.4.0"
version = "0.5.0"
edition = "2024"
description = "Portable Authenticode PKCS#7 trust verification (anchors, chain, EKU) using picky-rs"
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-azure-kv-rest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-azure-kv-rest"
version = "0.4.0"
version = "0.5.0"
edition = "2024"
description = "Azure Key Vault certificate metadata + keys/sign REST (portable, blocking HTTP)"
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-codesigning-rest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-codesigning-rest"
version = "0.4.0"
version = "0.5.0"
edition = "2024"
description = "Azure Code Signing data-plane CertificateProfileOperations Sign LRO (portable, blocking HTTP)"
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-digest-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-digest-cli"
version = "0.4.0"
version = "0.5.0"
edition = "2024"
description = "Linux/macOS-friendly CLI over portable Authenticode SIP digests (psign-sip-digest)"
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-opc-sign/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-opc-sign"
version = "0.4.0"
version = "0.5.0"
edition = "2024"
description = "Portable OPC, VSIX, and NuGet package signing primitives"
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-portable-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-portable-core"
version = "0.4.0"
version = "0.5.0"
edition = "2024"
description = "Reusable portable Authenticode signing and inspection APIs for psign"
license.workspace = true
Expand Down
Loading