Common.ps1 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. $ErrorActionPreference = 'Stop'
  2. Add-Type -AssemblyName System.Security
  3. function Save-ProtectedConfig {
  4. param([Parameter(Mandatory = $true)][object]$Config, [Parameter(Mandatory = $true)][string]$Path)
  5. $plainBytes = $null
  6. $cipherBytes = $null
  7. try {
  8. $json = $Config | ConvertTo-Json -Depth 8 -Compress
  9. $plainBytes = [Text.Encoding]::UTF8.GetBytes($json)
  10. $cipherBytes = [Security.Cryptography.ProtectedData]::Protect($plainBytes, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
  11. $directory = Split-Path -Parent $Path
  12. New-Item -ItemType Directory -Force -Path $directory | Out-Null
  13. $utf8NoBom = New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $false
  14. [IO.File]::WriteAllText($Path, [Convert]::ToBase64String($cipherBytes), $utf8NoBom)
  15. }
  16. finally {
  17. if ($plainBytes) { [Array]::Clear($plainBytes, 0, $plainBytes.Length) }
  18. if ($cipherBytes) { [Array]::Clear($cipherBytes, 0, $cipherBytes.Length) }
  19. }
  20. }
  21. function Get-ProtectedConfig {
  22. param([Parameter(Mandatory = $true)][string]$Path)
  23. if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { throw "Protected configuration not found: $Path" }
  24. $cipherBytes = $null
  25. $plainBytes = $null
  26. try {
  27. $cipherBytes = [Convert]::FromBase64String(([IO.File]::ReadAllText($Path)).Trim())
  28. $plainBytes = [Security.Cryptography.ProtectedData]::Unprotect($cipherBytes, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
  29. return ([Text.Encoding]::UTF8.GetString($plainBytes) | ConvertFrom-Json)
  30. }
  31. catch {
  32. throw 'Protected configuration cannot be decrypted by the current Windows user or is invalid.'
  33. }
  34. finally {
  35. if ($cipherBytes) { [Array]::Clear($cipherBytes, 0, $cipherBytes.Length) }
  36. if ($plainBytes) { [Array]::Clear($plainBytes, 0, $plainBytes.Length) }
  37. }
  38. }
  39. function Get-Sha256Hex {
  40. param([Parameter(Mandatory = $true)][byte[]]$Bytes)
  41. $sha = [Security.Cryptography.SHA256]::Create()
  42. try { return ([BitConverter]::ToString($sha.ComputeHash($Bytes))).Replace('-', '').ToLowerInvariant() }
  43. finally { $sha.Dispose() }
  44. }
  45. function New-SubmitKey {
  46. $bytes = New-Object byte[] 32
  47. [Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
  48. try { return ([Convert]::ToBase64String($bytes)).TrimEnd('=').Replace('+', '-').Replace('/', '_') }
  49. finally { [Array]::Clear($bytes, 0, $bytes.Length) }
  50. }
  51. function Write-HttpJson {
  52. param([Parameter(Mandatory = $true)]$Context, [Parameter(Mandatory = $true)][int]$StatusCode, [Parameter(Mandatory = $true)][object]$Body)
  53. $bytes = [Text.Encoding]::UTF8.GetBytes(($Body | ConvertTo-Json -Compress -Depth 6))
  54. try {
  55. $Context.Response.StatusCode = $StatusCode
  56. $Context.Response.ContentType = 'application/json; charset=utf-8'
  57. $Context.Response.ContentLength64 = $bytes.Length
  58. $Context.Response.OutputStream.Write($bytes, 0, $bytes.Length)
  59. }
  60. finally {
  61. if ($bytes) { [Array]::Clear($bytes, 0, $bytes.Length) }
  62. $Context.Response.Close()
  63. }
  64. }