Tests/Private/Checksum.Tests.ps1

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

Describe 'Private/Checksum' -Tag Unit {
    InModuleScope 'Posh-SecretSharing' {
        Describe 'Get-SecretSharingChecksumConstant' {
            It 'returns a checksum length of 3 words' {
                (Get-SecretSharingChecksumConstant).ChecksumLengthWords | Should -Be 3
            }
        }

        Describe 'Get-SecretSharingChecksumCustomizationString' {
            It 'returns "shamir" when not extendable' {
                $actual = Get-SecretSharingChecksumCustomizationString
                $actual | Should -Be ([System.Text.Encoding]::ASCII.GetBytes('shamir'))
            }

            It 'returns "shamir_extendable" when Extendable is set' {
                $actual = Get-SecretSharingChecksumCustomizationString -Extendable
                $actual | Should -Be ([System.Text.Encoding]::ASCII.GetBytes('shamir_extendable'))
            }
        }

        Describe 'Invoke-SecretSharingRs1024Polymod' {
            It 'is deterministic for identical input' {
                $values = [int[]](1, 2, 3, 4, 5)
                (Invoke-SecretSharingRs1024Polymod -Value $values) | Should -Be (Invoke-SecretSharingRs1024Polymod -Value $values)
            }

            It 'produces a different result when a single value changes' {
                $a = Invoke-SecretSharingRs1024Polymod -Value ([int[]](1, 2, 3))
                $b = Invoke-SecretSharingRs1024Polymod -Value ([int[]](1, 2, 4))
                $a | Should -Not -Be $b
            }
        }

        Describe 'New-SecretSharingChecksum / Test-SecretSharingChecksum' {
            It 'returns 3 words, each a valid 10-bit value' {
                $data = [int[]](1..10)
                $checksum = New-SecretSharingChecksum -Data $data
                $checksum.Count | Should -Be 3
                foreach ($word in $checksum) {
                    $word | Should -BeGreaterOrEqual 0
                    $word | Should -BeLessOrEqual 1023
                }
            }

            It 'produces a checksum that verifies against the same data' {
                $data = [int[]](1..12)
                $checksum = New-SecretSharingChecksum -Data $data
                $full = [int[]]($data + $checksum)
                Test-SecretSharingChecksum -Data $full | Should -BeTrue
            }

            It 'round-trips when Extendable is set on both sides' {
                $data = [int[]](500, 12, 900, 3, 42)
                $checksum = New-SecretSharingChecksum -Data $data -Extendable
                $full = [int[]]($data + $checksum)
                Test-SecretSharingChecksum -Data $full -Extendable | Should -BeTrue
            }

            It 'fails verification when Extendable does not match between creation and verification' {
                $data = [int[]](1..8)
                $checksum = New-SecretSharingChecksum -Data $data
                $full = [int[]]($data + $checksum)
                Test-SecretSharingChecksum -Data $full -Extendable | Should -BeFalse
            }

            It 'detects a single-word corruption at every position in Data + checksum' {
                $data = 1..12 | ForEach-Object { Get-Random -Minimum 0 -Maximum 1024 }
                $data = [int[]]$data
                $checksum = New-SecretSharingChecksum -Data $data
                $full = [int[]]($data + $checksum)

                for ($position = 0; $position -lt $full.Count; $position++) {
                    $corrupted = [int[]]$full.Clone()
                    $corrupted[$position] = ($corrupted[$position] -bxor 1023)
                    Test-SecretSharingChecksum -Data $corrupted | Should -BeFalse -Because "corrupting word $position must be detected"
                }
            }
        }
    }
}