Tests/Private/SecureString.Tests.ps1
|
BeforeDiscovery { Import-Module (Join-Path $PSScriptRoot '../../Posh-SecretSharing.psd1') -Force } Describe 'Private/SecureString' -Tag Unit { InModuleScope 'Posh-SecretSharing' { BeforeAll { function Get-TestPlainByte { param([System.Security.SecureString]$SecureString) $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($SecureString) try { $out = [byte[]]::new($SecureString.Length) for ($i = 0; $i -lt $SecureString.Length; $i++) { $out[$i] = [byte]([System.Runtime.InteropServices.Marshal]::ReadInt16($ptr, $i * 2) -band 0xFF) } return , $out } finally { [System.Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($ptr) } } # Builds a SecureString directly rather than via ConvertTo-SecureString, which is # unavailable in some Windows PowerShell 5.1 environments (a PSModulePath conflict # between the 5.1 and 7 copies of Microsoft.PowerShell.Security, unrelated to this # module) - confirmed to fail even outside Pester and outside this module. function New-TestSecureString { [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Test helper; pure in-memory construction, no external state is changed.')] param([string]$PlainText) $secure = New-Object System.Security.SecureString foreach ($ch in $PlainText.ToCharArray()) { $secure.AppendChar($ch) } return $secure } } Describe 'ConvertTo-SecretSharingSecureString / ConvertFrom-SecretSharingSecureString' { It 'round-trips an arbitrary byte array, including 0x00 and 0xFF' { $bytes = [byte[]](0x00, 0x01, 0x7F, 0x80, 0xFF, 0x41, 0x00) $secure = ConvertTo-SecretSharingSecureString -Byte $bytes $secure.Length | Should -Be $bytes.Count $back = ConvertFrom-SecretSharingSecureString -SecureString $secure $back | Should -Be $bytes } It 'round-trips a 32-byte value' { $bytes = 1..32 | ForEach-Object { [byte]$_ } $secure = ConvertTo-SecretSharingSecureString -Byte $bytes (ConvertFrom-SecretSharingSecureString -SecureString $secure) | Should -Be $bytes } It 'returns a read-only SecureString' { $secure = ConvertTo-SecretSharingSecureString -Byte ([byte[]](1, 2, 3)) $secure.IsReadOnly() | Should -BeTrue } } Describe 'ConvertFrom-SecretSharingPassphraseSecureString' { It 'encodes ASCII text as UTF-8 bytes' { $secure = New-TestSecureString -PlainText 'hunter2' $bytes = ConvertFrom-SecretSharingPassphraseSecureString -SecureString $secure $bytes | Should -Be ([System.Text.Encoding]::UTF8.GetBytes('hunter2')) } It 'encodes non-ASCII text correctly as UTF-8' { $secure = New-TestSecureString -PlainText 'caf' $secure.AppendChar([char]0xE9) $bytes = ConvertFrom-SecretSharingPassphraseSecureString -SecureString $secure $bytes | Should -Be ([System.Text.Encoding]::UTF8.GetBytes('caf' + [char]0xE9)) } It 'returns an empty array for an empty SecureString' { $secure = New-Object System.Security.SecureString (ConvertFrom-SecretSharingPassphraseSecureString -SecureString $secure).Count | Should -Be 0 } } } } |