Private/PivTool/ConvertFrom-PWSHYBKPIVSecureString.ps1

function ConvertFrom-PWSHYBKPIVSecureString {
    <#
    .SYNOPSIS
        Converts a SecureString to a plain-text string.
    .DESCRIPTION
        Marshals the SecureString to a BSTR, copies it to a managed string, and immediately
        zeroes and frees the unmanaged BSTR buffer. PowerShell 5.1 compatible (unlike
        ConvertFrom-SecureString -AsPlainText, which requires PowerShell 6+).

        The returned plain-text value exists only as long as needed to build a
        yubico-piv-tool.exe argument list; yubico-piv-tool.exe's own CLI interface requires
        secrets (PIN/PUK/management key/password) as literal command-line arguments, so the
        value will still be visible to OS-level process auditing (e.g. Sysmon) for the lifetime
        of the child process - that exposure is inherent to the wrapped tool's interface and
        cannot be avoided from PowerShell.
    .PARAMETER SecureString
        The SecureString to convert.
    .OUTPUTS
        String. The plain-text value.
    .EXAMPLE
        ConvertFrom-PWSHYBKPIVSecureString -SecureString $securePin
        Returns the plain-text PIN.
    #>

    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory)]
        [System.Security.SecureString] $SecureString
    )

    $bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
    try {
        [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
    } finally {
        [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
    }
}