Public/Get-ShamirSecretShares.ps1
<#
.SYNOPSIS Splits a secret into shares using Shamir's Secret Sharing scheme. .DESCRIPTION This function takes a secret string and splits it into shares using Shamir's Secret Sharing scheme. It first converts the secret into bytes, pads them, and splits them into chunks. Each chunk is then shared using Shamir's Secret Sharing, and the resulting shares are combined and serialized. .PARAMETER Secret The secret string to be shared. .PARAMETER Shares The total number of shares to generate. Defaults to 7. .PARAMETER MinimumShares The minimum number of shares required to reconstruct the secret. Defaults to 3. .OUTPUTS A serialized object containing an array of share objects, each with an ID, value, and chunk index. .EXAMPLE Share a secret: $Secret = "MySecretMessage" Get-ShamirSecretShares -Secret $Secret #> Function Get-ShamirSecretShares { Param( [Parameter(Mandatory)] [String]$Secret, [ValidateRange(2, [Int]::MaxValue)] [Int]$Shares = 7, [ValidateRange(2, [Int]::MaxValue)] [Alias('MinShares')] [Int]$MinimumShares = 3 ) # Validate the amount of shares. This is being done outside of Param() as the parameters would be handled differently if -MinShares would be given later If( $Shares -lt $MinimumShares) { Throw [System.Management.Automation.ValidationMetadataException] "$Shares shares and $MinimumShares minimum shares. The secret would not be recoverable." } # Convert the secret to bytes and pad them for a consistent length of the single secrets $Bytes = ConvertTo-Bytes $Secret | ForEach-Object { If($_ -lt 10) { "00$_" } ElseIf($_ -lt 100) { "0$_" } Else { "$_" } } $ChunkIndex = 0 # By splitting into chunks of 9 we manage to stay under 28 digits which would overflow [BigInt] $AllShares = Split-Array $Bytes -ChunkSize 9 | Foreach-Object { $Chunk = $_ $ChunkSecret = $Chunk -join '' $ChunkShares = Get-RandomShares -Secret $ChunkSecret -MinShares $MinimumShares -Shares $Shares Foreach ($Share in $ChunkShares) { [PSCustomObject]@{ id = $Share.id value = $Share.value.ToString() chunkindex = $ChunkIndex } } $ChunkIndex++ } $ZippedShares = ($AllShares | Group-Object -Property id).Name | Foreach-Object { $ShareId = $_ $SharesForId = $AllShares | Where-Object id -eq $ShareId $Data = Foreach ($Share in $SharesForId) { [PSCustomObject]@{ value = $Share.value.ToString() chunkindex = $Share.chunkindex } } [PSCustomObject]@{ Id = $ShareId Data = $Data } } $SerializedShares = Foreach( $ZippedShare in $ZippedShares) { [PSCustomObject]@{ Id = $ZippedShare.Id Share = $ZippedShare | ConvertTo-SerializedObject } } Return $SerializedShares } |