Tests/Public/New-SecretSharingPassword.Tests.ps1

BeforeDiscovery {
    Import-Module (Join-Path $PSScriptRoot '../../Posh-SecretSharing.psd1') -Force
}

Describe 'New-SecretSharingPassword' -Tag Unit {
    BeforeAll {
        function Get-TestPlainText {
            param([System.Security.SecureString]$SecureString)
            $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($SecureString)
            try {
                return [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr, $SecureString.Length)
            } finally {
                [System.Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($ptr)
            }
        }
    }

    It 'returns a SecureString' {
        (New-SecretSharingPassword -Entropy 128) | Should -BeOfType [System.Security.SecureString]
    }

    It 'returns a password long enough to carry the requested entropy, rounded to an even length' {
        # 75-character alphabet -> ~6.229 bits/character.
        (New-SecretSharingPassword -Entropy 128).Length | Should -Be 22
        (New-SecretSharingPassword -Entropy 256).Length | Should -Be 42
    }

    It 'throws for an unsupported entropy value' {
        { New-SecretSharingPassword -Entropy 64 } | Should -Throw
        { New-SecretSharingPassword -Entropy 512 } | Should -Throw
    }

    It 'only uses characters from the documented safe alphabet' {
        $plainText = Get-TestPlainText -SecureString (New-SecretSharingPassword -Entropy 256)
        $plainText | Should -Match '^[A-Za-z0-9!#%&*+\-.=@^_~]+$'
    }

    It 'produces different passwords on repeated calls' {
        $a = Get-TestPlainText -SecureString (New-SecretSharingPassword -Entropy 128)
        $b = Get-TestPlainText -SecureString (New-SecretSharingPassword -Entropy 128)
        $a | Should -Not -Be $b
    }

    Context 'round-trip through Split-/Join-SecretSharingSecret' {
        It 'recovers the exact original password text from a quorum of shares' {
            $password = New-SecretSharingPassword -Entropy 128
            $originalText = Get-TestPlainText -SecureString $password

            $shares = Split-SecretSharingSecret -Secret $password -Group @{ Threshold = 3; Count = 5 }
            $recovered = $shares | Select-Object -First 3 | Join-SecretSharingSecret
            $recoveredText = Get-TestPlainText -SecureString $recovered

            $recoveredText | Should -Be $originalText
        }
    }
}