Public/Get-DnsAcctLabel.ps1
|
function Get-DnsAcctLabel { [CmdletBinding()] param( [Parameter(Mandatory,Position=0,ValueFromPipelineByPropertyName)] [Alias('location')] [string]$AccountUri ) Begin { $sha256 = [Security.Cryptography.SHA256]::Create() [string[]]$b32Dict = 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','2','3','4','5','6','7' } Process { # https://datatracker.ietf.org/doc/draft-ietf-acme-dns-account-label/02/ # Construct the validation domain name by prepending the following two # labels to the domain name being validated: # # "_" || base32(SHA-256(<ACCOUNT_URL>)[0:10]) || "._acme-challenge" # - SHA-256 is the SHA hashing operation defined in [RFC6234] # - [0:10] is the operation that selects the first ten bytes # (bytes 0 through 9 inclusive) from the previous SHA-256 # operation # - base32 is the operation defined in [RFC4648] # - ACCOUNT_URL is defined in [RFC8555], Section 7.3 as the value # in the Location header field # - The || operator indicates concatenation of strings # Hash the AccountURI try { $hashBytes = [byte[]]$sha256.ComputeHash([Text.Encoding]::UTF8.GetBytes($AccountUri)) } catch { $PSCmdlet.WriteError($_) } # Now Base32 encode the first 10 bytes. This is not the most efficient way # to do Base32 encoding, but good enough for this very constrained purpose. # Write-Verbose ($hashBytes[0..9] -join ' ') # convert the first 10 bytes into binary and concatenate $hashChunkBinary = -join $hashBytes[0..9].ForEach{ [Convert]::ToString($_, 2).PadLeft(8, '0') } # Write-Verbose $hashChunkBinary # replace each 5-bit group with it's Base32 dictionary character $b32Val = [regex]::Replace($hashChunkBinary, '.{5}', { param($Match) $b32Dict[[Convert]::ToInt32($Match.Value, 2)] }) '_{0}._acme-challenge' -f $b32Val } End { $sha256.Dispose() } } |