Private/Crypto/Unprotect-SecretSharingMasterSecret.ps1
|
function Unprotect-SecretSharingMasterSecret { <# .SYNOPSIS Decrypts a master secret encrypted by Protect-SecretSharingMasterSecret. .DESCRIPTION Runs the same 4-round Feistel network as Protect-SecretSharingMasterSecret, but in reverse round order, which undoes the encryption exactly when Passphrase, Identifier, IterationExponent, and Extendable all match what was used to encrypt. There is no way to detect a wrong Passphrase from this function alone - it always returns some value of the right length, correct or not; a caller that needs to know whether decryption actually succeeded must check the result some other way (e.g. Test-SecretSharingDigestShare, once the reconstructed secret's shares have been recombined). #> [CmdletBinding()] [OutputType([byte[]], [System.Object[]])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Pure in-memory computation; no external state is changed.')] param( [Parameter(Mandatory)] [byte[]]$EncryptedMasterSecret, [byte[]]$Passphrase = @(), [Parameter(Mandatory)] [ValidateRange(0, 32767)] [int]$Identifier, [Parameter(Mandatory)] [ValidateRange(0, 15)] [int]$IterationExponent, [switch]$Extendable ) $constant = Get-SecretSharingCipherConstant if ($EncryptedMasterSecret.Length -lt $constant.MinimumSecretLength -or ($EncryptedMasterSecret.Length % 2) -ne 0) { throw "EncryptedMasterSecret must be an even number of bytes, at least $($constant.MinimumSecretLength)." } $saltPrefix = Get-SecretSharingCipherSaltPrefix -Identifier $Identifier -Extendable:$Extendable $half = [int]($EncryptedMasterSecret.Length / 2) $l = [byte[]]$EncryptedMasterSecret[0..($half - 1)] $r = [byte[]]$EncryptedMasterSecret[$half..($EncryptedMasterSecret.Length - 1)] for ($i = $constant.RoundCount - 1; $i -ge 0; $i--) { $f = Invoke-SecretSharingCipherRoundFunction -RoundIndex ([byte]$i) -Passphrase $Passphrase -SaltPrefix $saltPrefix -R $r -IterationExponent $IterationExponent $newR = [byte[]]::new($half) for ($b = 0; $b -lt $half; $b++) { $newR[$b] = $l[$b] -bxor $f[$b] } $l = $r $r = $newR } return , ([byte[]]($r + $l)) } |