Tests/Integration/OfficialVectors.Tests.ps1
|
BeforeDiscovery { Import-Module (Join-Path $PSScriptRoot '../../Posh-SecretSharing.psd1') -Force } <# Official SLIP-0039 test vectors from trezor/python-shamir-mnemonic's vectors.json, hardcoded here (no network access during test runs). Each vector's mnemonics were decrypted in the reference test suite with passphrase b"TREZOR" - see test_shamir.py. This is the only test in the whole suite that exercises every layer together (Wordlist, Checksum, Share, Shamir, Digest, Crypto) against data this module did not generate itself, so it's tagged Integration rather than Unit. #> Describe 'Official SLIP-0039 test vectors' -Tag Integration { InModuleScope 'Posh-SecretSharing' { BeforeAll { $script:Passphrase = [System.Text.Encoding]::ASCII.GetBytes('TREZOR') function Resolve-VectorShare { param([string]$Mnemonic) $wordIndex = @($Mnemonic -split ' ' | ForEach-Object { ConvertFrom-SecretSharingMnemonicWord -Word $_ }) $checksumOk = Test-SecretSharingChecksum -Data $wordIndex $header = ConvertFrom-SecretSharingShareWord -Index $wordIndex[0..($wordIndex.Count - 4)] return [PSCustomObject]@{ ChecksumOk = $checksumOk Header = $header } } } Context 'Vector 1: valid mnemonic without sharing (128 bits)' { It 'decrypts to the expected master secret' { $mnemonic = 'duckling enlarge academic academic agency result length solution fridge kidney coal piece deal husband erode duke ajar critical decision keyboard' $expected = [byte[]](0xbb, 0x54, 0xaa, 0xc4, 0xb8, 0x9d, 0xc8, 0x68, 0xba, 0x37, 0xd9, 0xcc, 0x21, 0xb2, 0xce, 0xce) $resolved = Resolve-VectorShare -Mnemonic $mnemonic $resolved.ChecksumOk | Should -BeTrue $secret = Unprotect-SecretSharingMasterSecret -EncryptedMasterSecret $resolved.Header.Value ` -Passphrase $script:Passphrase -Identifier $resolved.Header.Identifier ` -IterationExponent $resolved.Header.IterationExponent -Extendable:$resolved.Header.Extendable $secret | Should -Be $expected } } Context 'Vector 2: mnemonic with invalid checksum (128 bits)' { It 'fails checksum verification' { $mnemonic = 'duckling enlarge academic academic agency result length solution fridge kidney coal piece deal husband erode duke ajar critical decision kidney' (Resolve-VectorShare -Mnemonic $mnemonic).ChecksumOk | Should -BeFalse } } Context 'Vector 3: mnemonic with invalid padding (128 bits)' { It 'passes checksum verification but fails to decode (invalid padding is a separate check)' { $mnemonic = 'duckling enlarge academic academic email result length solution fridge kidney coal piece deal husband erode duke ajar music cargo fitness' $wordIndex = @($mnemonic -split ' ' | ForEach-Object { ConvertFrom-SecretSharingMnemonicWord -Word $_ }) Test-SecretSharingChecksum -Data $wordIndex | Should -BeTrue { ConvertFrom-SecretSharingShareWord -Index $wordIndex[0..($wordIndex.Count - 4)] } | Should -Throw } } Context 'Vector 4: basic sharing 2-of-3 (128 bits)' { It 'combines 2 of the 3 shares and decrypts to the expected master secret' { $mnemonics = @( 'shadow pistol academic always adequate wildlife fancy gross oasis cylinder mustang wrist rescue view short owner flip making coding armed', 'shadow pistol academic acid actress prayer class unknown daughter sweater depict flip twice unkind craft early superior advocate guest smoking' ) $expected = [byte[]](0xb4, 0x3c, 0xeb, 0x7e, 0x57, 0xa0, 0xea, 0x87, 0x66, 0x22, 0x16, 0x24, 0xd0, 0x1b, 0x08, 0x64) $resolved = $mnemonics | ForEach-Object { Resolve-VectorShare -Mnemonic $_ } foreach ($r in $resolved) { $r.ChecksumOk | Should -BeTrue } $first = $resolved[0].Header $first.GroupThreshold | Should -Be 1 $first.GroupCount | Should -Be 1 $memberPoint = $resolved | ForEach-Object { [PSCustomObject]@{ X = [byte]$_.Header.MemberIndex; Value = $_.Header.Value } } $digestConstant = Get-SecretSharingDigestConstant $ems = Invoke-SecretSharingShamirInterpolation -Point $memberPoint -X $digestConstant.SecretIndex $digestShare = Invoke-SecretSharingShamirInterpolation -Point $memberPoint -X $digestConstant.DigestIndex Test-SecretSharingDigestShare -Secret $ems -DigestShare $digestShare | Should -BeTrue $secret = Unprotect-SecretSharingMasterSecret -EncryptedMasterSecret $ems -Passphrase $script:Passphrase ` -Identifier $first.Identifier -IterationExponent $first.IterationExponent -Extendable:$first.Extendable $secret | Should -Be $expected } It 'fails to combine from a single share (below the 2-of-3 threshold)' { $mnemonic = 'shadow pistol academic always adequate wildlife fancy gross oasis cylinder mustang wrist rescue view short owner flip making coding armed' $resolved = Resolve-VectorShare -Mnemonic $mnemonic $resolved.ChecksumOk | Should -BeTrue $resolved.Header.MemberThreshold | Should -Be 2 # A real Join-SecretSharingSecret cmdlet will need to detect "not enough shares yet" # itself and refuse to proceed - there's nothing at the Shamir layer that can, since # a single point is mathematically consistent with infinitely many possible secrets. } } } } |