diff --git a/Docs/Commands/Confirm-YubiKeyFIDO2Attestation.md b/Docs/Commands/Confirm-YubiKeyFIDO2Attestation.md new file mode 100644 index 0000000..e7b4671 --- /dev/null +++ b/Docs/Commands/Confirm-YubiKeyFIDO2Attestation.md @@ -0,0 +1,86 @@ +--- +document type: cmdlet +external help file: powershellYK.dll-Help.xml +HelpUri: '' +Locale: en-SE +Module Name: powershellYK +ms.date: 03-26-2026 +PlatyPS schema version: 2024-05-01 +title: Confirm-YubiKeyFIDO2Attestation +--- + +# Confirm-YubiKeyFIDO2Attestation + +## SYNOPSIS + +{{ Fill in the Synopsis }} + +## SYNTAX + +### __AllParameterSets + +``` +Confirm-YubiKeyFIDO2Attestation -AttestationObject [] +``` + +## ALIASES + +This cmdlet has the following aliases, + {{Insert list of aliases}} + +## DESCRIPTION + +{{ Fill in the Description }} + +## EXAMPLES + +### Example 1 + +{{ Add example description here }} + +## PARAMETERS + +### -AttestationObject + +Path to attestation file (e.g. attestation.bin from ssh-keygen -O write-attestation) + +```yaml +Type: System.IO.FileInfo +DefaultValue: '' +SupportsWildcards: false +Aliases: [] +ParameterSets: +- Name: (All) + Position: Named + IsRequired: true + ValueFromPipeline: false + ValueFromPipelineByPropertyName: false + ValueFromRemainingArguments: false +DontShow: false +AcceptedValues: [] +HelpMessage: '' +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, +-InformationAction, -InformationVariable, -OutBuffer, -OutVariable, -PipelineVariable, +-ProgressAction, -Verbose, -WarningAction, and -WarningVariable. For more information, see +[about_CommonParameters](https://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Object + +{{ Fill in the Description }} + +## NOTES + +{{ Fill in the Notes }} + +## RELATED LINKS + +{{ Fill in the related links here }} + diff --git a/Docs/Commands/New-Challenge.md b/Docs/Commands/New-Challenge.md new file mode 100644 index 0000000..8eda0b5 --- /dev/null +++ b/Docs/Commands/New-Challenge.md @@ -0,0 +1,128 @@ +--- +document type: cmdlet +external help file: powershellYK.dll-Help.xml +HelpUri: '' +Locale: en-SE +Module Name: powershellYK +ms.date: 03-26-2026 +PlatyPS schema version: 2024-05-01 +title: New-Challenge +--- + +# New-Challenge + +## SYNOPSIS + +Creates a pseudo random challenge to support FIDO2 attestation output (among other things). + +## SYNTAX + +### __AllParameterSets + +``` +New-Challenge -OutFile [-Length ] [-Force] [] +``` + +## ALIASES + +## DESCRIPTION + +Creates a pseudo random challenge to support FIDO2 attestation output (among other things). + +## EXAMPLES + +### Example 1 + +´``powershell +New-Challenge -OutFile "MyChallenge.bin" -Length 256 +``` +Creates a 256-byte challenge and writes it to "MyChallenge.bin" + +## PARAMETERS + +### -Force + +Force overwriting existing files. + +```yaml +Type: System.Management.Automation.SwitchParameter +DefaultValue: '' +SupportsWildcards: false +Aliases: [] +ParameterSets: +- Name: (All) + Position: Named + IsRequired: false + ValueFromPipeline: false + ValueFromPipelineByPropertyName: false + ValueFromRemainingArguments: false +DontShow: false +AcceptedValues: [] +HelpMessage: '' +``` + +### -Length + +Length of the challenge in bytes + +```yaml +Type: System.Int32 +DefaultValue: '' +SupportsWildcards: false +Aliases: [] +ParameterSets: +- Name: (All) + Position: Named + IsRequired: false + ValueFromPipeline: false + ValueFromPipelineByPropertyName: false + ValueFromRemainingArguments: false +DontShow: false +AcceptedValues: [] +HelpMessage: '' +``` + +### -OutFile + +Path for the output file. + +```yaml +Type: System.IO.FileInfo +DefaultValue: '' +SupportsWildcards: false +Aliases: [] +ParameterSets: +- Name: (All) + Position: Named + IsRequired: true + ValueFromPipeline: false + ValueFromPipelineByPropertyName: false + ValueFromRemainingArguments: false +DontShow: false +AcceptedValues: [] +HelpMessage: '' +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, +-InformationAction, -InformationVariable, -OutBuffer, -OutVariable, -PipelineVariable, +-ProgressAction, -Verbose, -WarningAction, and -WarningVariable. For more information, see +[about_CommonParameters](https://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Object + +{{ Fill in the Description }} + +## NOTES + +{{ Fill in the Notes }} + +## RELATED LINKS + +{{ Fill in the related links here }} + diff --git a/Docs/Commands/powershellYK.md b/Docs/Commands/powershellYK.md index 110f39a..e616ad0 100644 --- a/Docs/Commands/powershellYK.md +++ b/Docs/Commands/powershellYK.md @@ -5,7 +5,7 @@ HelpInfoUri: '' Locale: en-US Module Guid: d947dd9b-87eb-49ea-a373-b91c7acc0917 Module Name: powershellYK -ms.date: 03-19-2026 +ms.date: 03-27-2026 PlatyPS schema version: 2024-05-01 System.Collections.Generic.Dictionary`2[System.Object,System.Object]: '' --- @@ -34,6 +34,10 @@ Creates a CSR for a slot in the YubiKey. Sign a certificate request with a YubiKey. +### [Confirm-YubiKeyFIDO2Attestation](Confirm-YubiKeyFIDO2Attestation.md) + +{{ Fill in the Synopsis }} + ### [Confirm-YubiKeyPIVAttestation](Confirm-YubiKeyPIVAttestation.md) Confirm YubiKey Attestation. @@ -70,6 +74,10 @@ Enables logging from the Yubico SDK. Enables the Enterprise Attestion feature on the YubiKey FIDO2 device. +### [Export-YubiKeyFIDO2Blob](Export-YubiKeyFIDO2Blob.md) + +Exports large blob from YubiKey FIDO2 by Credential ID or Relying Party ID (Origin). + ### [Export-YubiKeyPIVCertificate](Export-YubiKeyPIVCertificate.md) Export certificate from YubiKey PIV @@ -114,6 +122,10 @@ YubiKey OTP Information Gets information about the PIV module and specific slots. +### [Import-YubiKeyFIDO2Blob](Import-YubiKeyFIDO2Blob.md) + +Imports large blob to YubiKey FIDO2 by Credential ID or Relying Party ID (Origin). + ### [Import-YubiKeyPIV](Import-YubiKeyPIV.md) Import certificate @@ -126,6 +138,10 @@ Lock the YubiKey configuration Move a key from one slot to another +### [New-Challenge](New-Challenge.md) + +Creates a pseudo random challenge to support FIDO2 attestation output (among other things). + ### [New-YubiKeyFIDO2Credential](New-YubiKeyFIDO2Credential.md) Creates a new FIDO2 credential on the connected YubiKey. diff --git a/Module/Cmdlets/Other/GetChallenge.cs b/Module/Cmdlets/Other/GetChallenge.cs deleted file mode 100644 index 68f9b25..0000000 --- a/Module/Cmdlets/Other/GetChallenge.cs +++ /dev/null @@ -1,50 +0,0 @@ -/// -/// Creates a pseudo random challenge to support FIDO2 attestation output (among other things). -/// Uses cryptographically secure random data via RandomNumberGenerator. -/// Writes the challenge to a file only; defaults to "challenge.bin" if -OutFile is not specified. -/// -/// .EXAMPLE -/// Get-Challenge -/// Creates a 128-byte challenge and writes it to "challenge.bin" -/// -/// .EXAMPLE -/// Get-Challenge -Length 256 -/// Creates a 256-byte challenge and writes it to "challenge.bin" -/// -/// .EXAMPLE -/// Get-Challenge -OutFile "MyChallenge.bin" -/// Creates a 128-byte challenge and writes it to "MyChallenge.bin" -/// - -// Imports -using System.Management.Automation; -using System.Security.Cryptography; - -namespace powershellYK.Cmdlets.Other -{ - [Cmdlet(VerbsCommon.Get, "Challenge")] - public class GetChallengeCommand : Cmdlet - { - [Parameter(Mandatory = false, HelpMessage = "Length of the challenge in bytes")] - [ValidateRange(1, 4096)] - public int Length { get; set; } = 128; - - [Parameter(Mandatory = false, HelpMessage = "Path for the output file. Defaults to challenge.bin")] - public string? OutFile { get; set; } - - // Process the main cmdlet logic - protected override void ProcessRecord() - { - // Generate cryptographically secure random challenge bytes - byte[] challenge = new byte[Length]; - RandomNumberGenerator.Fill(challenge); - - // Determine output path; default to challenge.bin when not specified - string path = string.IsNullOrEmpty(OutFile) ? "challenge.bin" : OutFile; - System.IO.File.WriteAllBytes(path, challenge); - - // Confirm completion to the user - WriteInformation($"Challenge of length {Length} generated and written to file '{path}'.", new[] { "Challenge", "Info" }); - } - } -} diff --git a/Module/Cmdlets/Other/NewChallenge.cs b/Module/Cmdlets/Other/NewChallenge.cs index 2c00c0d..e6c69f8 100644 --- a/Module/Cmdlets/Other/NewChallenge.cs +++ b/Module/Cmdlets/Other/NewChallenge.cs @@ -2,39 +2,43 @@ /// Creates a pseudo random challenge to support FIDO2 attestation output (among other things). /// Uses cryptographically secure random data via RandomNumberGenerator. /// Writes the challenge to a file only; defaults to "challenge.bin" if -OutFile is not specified. +/// Default length is 128 bytes. /// /// .EXAMPLE -/// Get-Challenge +/// New-Challenge /// Creates a 128-byte challenge and writes it to "challenge.bin" /// /// .EXAMPLE -/// Get-Challenge -Length 256 +/// New-Challenge -Length 256 /// Creates a 256-byte challenge and writes it to "challenge.bin" /// /// .EXAMPLE -/// Get-Challenge -OutFile "MyChallenge.bin" +/// New-Challenge -OutFile "MyChallenge.bin" /// Creates a 128-byte challenge and writes it to "MyChallenge.bin" +/// +/// .EXAMPLE +/// New-Challenge -OutFile "MyChallenge.bin" -Force +/// Overwrites MyChallenge.bin if it already exists /// // Imports -using powershellYK.support.transform; -using powershellYK.support.validators; using System.IO; using System.Management.Automation; using System.Security.Cryptography; +using powershellYK.support.transform; namespace powershellYK.Cmdlets.Other { [Cmdlet(VerbsCommon.New, "Challenge")] - public class NewChallengeCommand : Cmdlet + public class NewChallengeCommand : PSCmdlet { [Parameter(Mandatory = false, HelpMessage = "Length of the challenge in bytes")] [ValidateRange(1, 4096)] public int Length { get; set; } = 128; + [Parameter(Mandatory = false, HelpMessage = "Path for the output file. Defaults to challenge.bin")] [TransformPath] - [Parameter(Mandatory = true, HelpMessage = "Path for the output file.")] - public required System.IO.FileInfo OutFile { get; set; } + public FileInfo? OutFile { get; set; } [Parameter(Mandatory = false, HelpMessage = "Force overwriting existing files.")] public SwitchParameter Force { get; set; } = false; @@ -42,24 +46,26 @@ public class NewChallengeCommand : Cmdlet // Process the main cmdlet logic protected override void ProcessRecord() { - if (OutFile.Exists && !Force.IsPresent) + // Determine output path; default to challenge.bin in the current PowerShell location + if (OutFile is null) { - var ex = new IOException($"File already exists: {OutFile.FullName}"); - ex.HResult = unchecked((int)0x80070050); // ERROR_FILE_EXISTS - throw ex; + string pswd = SessionState.Path.CurrentFileSystemLocation.Path; + OutFile = new FileInfo(Path.Combine(pswd, "challenge.bin")); } + string path = OutFile.FullName; + // Generate cryptographically secure random challenge bytes byte[] challenge = new byte[Length]; RandomNumberGenerator.Fill(challenge); - // Determine output path; default to challenge.bin when not specified - using (var file = OutFile.OpenWrite()) + // CreateNew fails atomically if file exists; Create allows overwrite + using (var fs = new FileStream(path, Force.IsPresent ? FileMode.Create : FileMode.CreateNew)) { - file.Write(challenge); + fs.Write(challenge, 0, challenge.Length); } - // Confirm completion to the user - WriteInformation($"Challenge of length {Length} generated and written to file '{OutFile.FullName}'.", new[] { "Challenge", "Info" }); + + WriteInformation($"Challenge of length {Length} generated and written to file '{path}'.", new[] { "Challenge", "Info" }); } } } diff --git a/Pester/991-Get-Challenge.tests.ps1 b/Pester/991-New-Challenge.tests.ps1 similarity index 77% rename from Pester/991-Get-Challenge.tests.ps1 rename to Pester/991-New-Challenge.tests.ps1 index 7a47a00..05ae854 100644 --- a/Pester/991-Get-Challenge.tests.ps1 +++ b/Pester/991-New-Challenge.tests.ps1 @@ -15,6 +15,22 @@ Describe "New-Challenge" -Tag "Without-YubiKey" { (Get-Item $outFile).Length | Should -Be 128 } + It -Name "Defaults to challenge.bin in current directory when -OutFile omitted" -Test { + $tempDir = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [Guid]::NewGuid().ToString('n')) + New-Item -ItemType Directory -Path $tempDir | Out-Null + try { + Push-Location $tempDir + New-Challenge + $defaultPath = Join-Path $tempDir 'challenge.bin' + (Test-Path $defaultPath) | Should -Be $true + (Get-Item $defaultPath).Length | Should -Be 128 + } + finally { + Pop-Location + Remove-Item -LiteralPath $tempDir -Recurse -Force -ErrorAction SilentlyContinue + } + } + It -Name "Creates file with -Length 256" -Test { New-Challenge -Length 256 -OutFile $outFile (Get-Item $outFile).Length | Should -Be 256