Private/Storage/ActiveDirectory/Unprotect-PukAdAttributeValue.ps1
|
function Unprotect-PukAdAttributeValue { [CmdletBinding()] [OutputType([psobject])] param( [Parameter(Mandatory)] [string]$Value, [Parameter(Mandatory)] [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate ) function Test-PukConstantTimeEqual { param([byte[]]$A, [byte[]]$B) if ($A.Length -ne $B.Length) { return $false } $diff = 0 for ($i = 0; $i -lt $A.Length; $i++) { $diff = $diff -bor ($A[$i] -bxor $B[$i]) } return $diff -eq 0 } $parts = $Value -split '\.' if ($parts.Count -ne 4) { throw "PWSHPUKMGT AD attribute value is not in the expected 'wrappedKey.iv.ciphertext.mac' format." } $wrappedKey = [Convert]::FromBase64String($parts[0]) $iv = [Convert]::FromBase64String($parts[1]) $cipherBytes = [Convert]::FromBase64String($parts[2]) $mac = [Convert]::FromBase64String($parts[3]) $combinedKeyMaterial = Unprotect-PukAesKeyWithCertificate -WrappedKey $wrappedKey -Certificate $Certificate $key = $combinedKeyMaterial[0..31] $hmacKey = $combinedKeyMaterial[32..63] $hmac = [System.Security.Cryptography.HMACSHA256]::new($hmacKey) try { $expectedMac = $hmac.ComputeHash($iv + $cipherBytes) } finally { $hmac.Dispose() } if (-not (Test-PukConstantTimeEqual -A $mac -B $expectedMac)) { throw 'PWSHPUKMGT AD attribute value failed integrity verification (HMAC mismatch) -- it may have been tampered with or corrupted.' } $aes = [System.Security.Cryptography.Aes]::Create() try { $aes.Key = $key $aes.IV = $iv $decryptor = $aes.CreateDecryptor() try { $plaintextBytes = $decryptor.TransformFinalBlock($cipherBytes, 0, $cipherBytes.Length) } finally { $decryptor.Dispose() } } finally { $aes.Dispose() } return [System.Text.Encoding]::UTF8.GetString($plaintextBytes) | ConvertFrom-Json } |