Core/Protect-TestSecret.ps1

function Protect-TestSecret {
    <#
    .SYNOPSIS
        Encrypts a secret for storage on disk where the platform can, and says so where it cannot

    .DESCRIPTION
        A provider's durable credential - a service account token, a service account password -
        has to be written somewhere. On Windows it is protected with DPAPI through
        ConvertFrom-SecureString, which ties it to the user and machine that wrote it. Anywhere
        else ConvertFrom-SecureString returns a hex encoding of the plaintext rather than
        anything encrypted, so this refuses to call the result protected: it warns, returns the
        value with Method None, and points at -UseSecretStore, which is the portable path.

        The result is checked rather than trusted. The protected value must differ from the
        input, and where it is hex it must not decode to something containing the plaintext,
        because that is exactly what an unencrypted platform produces.

        Shared by every provider that keeps a credential record, so the check lives once.

    .PARAMETER PlainText
        The secret to protect.

    .OUTPUTS
        PSCustomObject with Method (DPAPI or None) and Value.

    .EXAMPLE
        PS> $protected = Protect-TestSecret -PlainText $token

        DESCRIPTION: Protects a secret for a credential record
        OUTPUT: Method 'DPAPI' and an opaque value on Windows
        USE CASE: A provider's Export-<Provider>Credential

    .NOTES
        Author: Jeffrey Stuhr
        Blog: https://www.techbyjeff.net
        LinkedIn: https://www.linkedin.com/in/jeffrey-stuhr-034214aa/
    #>


    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '',
        Justification = 'The plaintext is the value being protected; the SecureString is the route to DPAPI.')]
    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$PlainText
    )

    try {
        $onWindows = ($PSVersionTable.PSEdition -eq 'Desktop') -or
            ($PSVersionTable.PSObject.Properties['Platform'] -and $PSVersionTable.Platform -eq 'Win32NT') -or
            ($env:OS -eq 'Windows_NT')
        if (-not $onWindows) {
            throw 'DPAPI is only available on Windows.'
        }

        $secure = ConvertTo-SecureString -String $PlainText -AsPlainText -Force
        $protected = ConvertFrom-SecureString -SecureString $secure -ErrorAction Stop

        if ([string]::IsNullOrWhiteSpace($protected) -or $protected -eq $PlainText) {
            throw 'ConvertFrom-SecureString did not return a protected value.'
        }

        if ($protected -match '^[0-9a-fA-F]+$' -and ($protected.Length % 2) -eq 0) {
            try {
                $raw = [byte[]]::new($protected.Length / 2)
                for ($i = 0; $i -lt $raw.Length; $i++) {
                    $raw[$i] = [Convert]::ToByte($protected.Substring($i * 2, 2), 16)
                }
                if ([System.Text.Encoding]::Unicode.GetString($raw).Contains($PlainText)) {
                    throw 'the protected value still contains the plaintext.'
                }
            }
            catch [System.FormatException] {
                Write-Verbose 'Protected value is not a hex encoding, which is the desired outcome.'
            }
        }

        return [PSCustomObject]@{ Method = 'DPAPI'; Value = $protected }
    }
    catch {
        Write-Warning ("This platform cannot encrypt the credential at rest with DPAPI " +
            "($($_.Exception.Message)). The secret will be written UNPROTECTED, guarded only by " +
            'file permissions. Pass -UseSecretStore for encrypted storage here.')
        return [PSCustomObject]@{ Method = 'None'; Value = $PlainText }
    }
}