MappingEncrypt.psm1
|
#Requires -Version 5.1 <# MappingEncrypt — PowerShell port of the "mapping-encrypt" Python package. Identical behavior: encodes/decodes text through the SAME private Cloudflare mapping worker (same URL, same API key, same /encode and /decode endpoints, same "|" delimiter). Encoding a script produces a self-decoding stub that fetches the decode from Cloudflare at runtime and runs it via Invoke-Expression (the PowerShell equivalent of Python's exec()). Python -> PowerShell mapping.encode(text) -> ConvertTo-MappingEncoded mapping.decode(encoded) -> ConvertFrom-MappingEncoded mapping-encode (CLI) -> Protect-MappingScript (alias: mapping-encode) mapping-decode (CLI) -> Unprotect-MappingScript (alias: mapping-decode) mapping-pkg (CLI) -> Invoke-MappingPackage #> $script:WorkerUrl = 'https://mapping-worker.email-ecf.workers.dev' $script:ApiKey = 'b19b8317f4c0239b7df33d5199ba67dfd40291da28d56f3697e8f455d9953774' function ConvertTo-MappingEncoded { <# .SYNOPSIS Encode text into mapping tokens via the Cloudflare worker. (= Python mapping.encode) #> [CmdletBinding()] param( [Parameter(Mandatory, Position = 0, ValueFromPipeline)] [string] $Text, [string] $Delimiter = '|' ) process { $payload = @{ text = $Text; delimiter = $Delimiter } | ConvertTo-Json -Compress -Depth 5 $bytes = [System.Text.Encoding]::UTF8.GetBytes($payload) try { $resp = Invoke-RestMethod -Uri "$script:WorkerUrl/encode" -Method Post -Body $bytes ` -Headers @{ 'X-API-Key' = $script:ApiKey } -ContentType 'application/json; charset=utf-8' } catch { $detail = $_.ErrorDetails.Message if ($detail) { try { $detail = ($detail | ConvertFrom-Json).error } catch { } throw "Encoding failed: $detail" } throw } return $resp.encoded } } function ConvertFrom-MappingEncoded { <# .SYNOPSIS Decode mapping tokens back into text via the Cloudflare worker. (= Python mapping.decode) #> [CmdletBinding()] param( [Parameter(Mandatory, Position = 0, ValueFromPipeline)] [string] $EncodedString, [string] $Delimiter = '|', [switch] $Strict ) process { $payload = @{ encoded = $EncodedString; delimiter = $Delimiter; strict = [bool]$Strict } | ConvertTo-Json -Compress -Depth 5 $bytes = [System.Text.Encoding]::UTF8.GetBytes($payload) $resp = Invoke-RestMethod -Uri "$script:WorkerUrl/decode" -Method Post -Body $bytes ` -Headers @{ 'X-API-Key' = $script:ApiKey } -ContentType 'application/json; charset=utf-8' return $resp.decoded } } function Protect-MappingScript { <# .SYNOPSIS Encode a .ps1 file into a self-decoding stub. (= Python mapping-encode CLI) #> [CmdletBinding()] [Alias('mapping-encode')] param( [Parameter(Mandatory, Position = 0)] [string] $Path, [Parameter(Position = 1)] [Alias('o', 'OutputPath')] [string] $OutputFile ) if (-not (Test-Path -LiteralPath $Path)) { throw "Input file not found: $Path" } $text = Get-Content -LiteralPath $Path -Raw -Encoding UTF8 $encoded = ConvertTo-MappingEncoded -Text $text if (-not $OutputFile) { $dir = Split-Path -Parent $Path $base = [System.IO.Path]::GetFileNameWithoutExtension($Path) $ext = [System.IO.Path]::GetExtension($Path) if (-not $ext) { $ext = '.ps1' } $name = "${base}_encoded${ext}" $OutputFile = if ($dir) { Join-Path $dir $name } else { $name } } # Single-quoted so tokens containing '$' (e.g. the '"' token c$HCi) are NOT # treated as PowerShell variables. Tokens never contain a single quote. $stub = @" Import-Module MappingEncrypt `$encodedString = '$encoded' `$decodedString = ConvertFrom-MappingEncoded -EncodedString `$encodedString Invoke-Expression `$decodedString "@ Set-Content -LiteralPath $OutputFile -Value $stub -Encoding UTF8 Write-Host "Encoded script saved to $OutputFile" return $OutputFile } function Unprotect-MappingScript { <# .SYNOPSIS Decode an encrypted .ps1 file back to raw code. (= Python mapping-decode CLI) #> [CmdletBinding()] [Alias('mapping-decode')] param( [Parameter(Mandatory, Position = 0)] [string] $Path, [Parameter(Position = 1)] [Alias('o', 'OutputPath')] [string] $OutputFile ) if (-not (Test-Path -LiteralPath $Path)) { throw "Input file not found: $Path" } $content = Get-Content -LiteralPath $Path -Raw -Encoding UTF8 $match = [regex]::Match($content, "\`$encodedString\s*=\s*['`"]([^'`"]+)['`"]") if (-not $match.Success) { throw "No encodedString found in file - is this an encrypted script?" } $encoded = $match.Groups[1].Value $raw = ConvertFrom-MappingEncoded -EncodedString $encoded if (-not $OutputFile) { $base = $Path -replace '_encoded\.ps1$', '.ps1' -replace '_encrypted\.ps1$', '.ps1' if ($base -ne $Path) { $OutputFile = $base } else { $OutputFile = $Path -replace '\.ps1$', '_decoded.ps1' } } Set-Content -LiteralPath $OutputFile -Value $raw -Encoding UTF8 -NoNewline Write-Host "Decoded script saved to $OutputFile" return $OutputFile } function Invoke-MappingPackage { <# .SYNOPSIS Install / uninstall / reinstall the module from PowerShell Gallery. (= Python mapping-pkg CLI) #> [CmdletBinding()] param( [Parameter(Mandatory, Position = 0)] [ValidateSet('install', 'uninstall', 'reinstall')] [string] $Action ) $module = 'MappingEncrypt' switch ($Action) { 'install' { Install-Module $module -Scope CurrentUser -Force Write-Host 'Done.' } 'uninstall' { Uninstall-Module $module -AllVersions -Force Write-Host 'Done.' } 'reinstall' { Uninstall-Module $module -AllVersions -Force Install-Module $module -Scope CurrentUser -Force Write-Host 'Done.' } } } Export-ModuleMember -Function ConvertTo-MappingEncoded, ConvertFrom-MappingEncoded, Protect-MappingScript, Unprotect-MappingScript, Invoke-MappingPackage ` -Alias 'mapping-encode', 'mapping-decode' |