Private/Security.psm1

#!/usr/bin/env pwsh
using namespace System
using namespace System.Text
using namespace System.Security.Cryptography

class RequestValidator {
  hidden [string] $AuthToken

  RequestValidator([string]$authToken) {
    $this.AuthToken = $authToken
  }

  hidden [string] ComputeSignature([string]$url, [hashtable]$params) {
    $data = $url
    if ($null -ne $params) {
      foreach ($key in ($params.Keys | Sort-Object)) {
        $data += [string]$key + [string]$params[$key]
      }
    }

    $hmac = [HMACSHA1]::new([Encoding]::UTF8.GetBytes($this.AuthToken))
    try {
      $hash = $hmac.ComputeHash([Encoding]::UTF8.GetBytes($data))
      return [Convert]::ToBase64String($hash)
    } finally {
      $hmac.Dispose()
    }
  }

  [bool] Validate([string]$url, [hashtable]$params, [string]$expectedSignature) {
    if ([string]::IsNullOrWhiteSpace($expectedSignature)) { return $false }
    $calculated = $this.ComputeSignature($url, $params)
    return [string]::Equals($calculated, $expectedSignature, [StringComparison]::Ordinal)
  }
}