HiddenString.ps1

class HiddenString {
    hidden [SecureString]$SecureString = [SecureString]::new()

    hidden New([Object]$Object, [Bool]$Warn) {
        if ($Object -is [SecureString]) { $This.SecureString = $Object }
        elseif ($Object -is [HiddenString]) { $This.SecureString = $Object.SecureString }
        elseif ($Object -is [Byte[]]) {
            $String = [System.Text.StringBuilder]::new()
            foreach ($Byte in $Object) {
                $x2 = '{0:x2}' -f $Byte
                [void]$String.Append($x2)
            }
            $This.SecureString = ConvertTo-SecureString $String
        }
        elseif ($Object) { $This.Add($Object, $Warn) }
    }
    HiddenString()                       { $This.New($Null,   $True) }
    HiddenString([Object]$Object)        { $This.New($Object, $True) }
    HiddenString([Object]$Object, $Warn) { $This.New($Object, $Warn) }
    static [HiddenString]FromBase64Cypher([string]$String) { return [System.Convert]::FromBase64String($String) }

    [Void]Clear() { $This.SecureString.Clear() }
    [Void]Add([Char[]]$Characters) { $This.Add($Characters, $True) }
    [Void]Add([Char[]]$Characters, [bool]$Warn) {
        if ($Warn -and $Characters.Count -gt 1) { Write-Warning 'For better obscurity, use a hidden or secure string for input.' }
        $Characters.ForEach{ $This.SecureString.AppendChar($_) }
    }
    [Bool]Equals($Object) { return $This.SecureString.Equals($Object.SecureString)}
    [SecureString]ToSecureString() { return $This.SecureString }
    [String]Reveal() { return $This.Reveal($True) }
    [String]Reveal($Warn) {
        if ($Warn) { Write-Warning 'For better obscurity, use a secure string output.' }
        $Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($This.SecureString)
        $String = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($Ptr)
        [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($Ptr)
        return $String
    }
    [Void]Dispose() { $This.SecureString.Dispose() }
}

class HiddenString2SecureString : System.Management.Automation.PSTypeConverter
{
    [bool] CanConvertFrom([object]$sourceValue, [Type]$destinationType)
    { return $false }

    [object] ConvertFrom([object]$sourceValue, [Type]$destinationType, [IFormatProvider]$formatProvider, [bool]$ignoreCase)
    { throw [NotImplementedException]::new() }

    [bool] CanConvertTo([object]$sourceValue, [Type]$destinationType)
    { return ($destinationType -eq [System.Security.SecureString])}

    [object] ConvertTo([object]$sourceValue, [Type]$destinationType, [IFormatProvider]$formatProvider, [bool]$ignoreCase)
    { return $sourceValue.SecureString }
}
Update-TypeData -Force -TypeName HiddenString -TypeConverter HiddenString2SecureString