functions/public/ConvertTo-SodiumString.ps1

function ConvertTo-SodiumString {
    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory, ValueFromPipeline)]
        [AllowEmptyString()]
        [string]$InputObject,

        [Parameter(Mandatory)]
        [object]$Key
    )

    begin {
        Initialize-SodiumType
        $keyBytes = Resolve-SodiumKey -Key $Key
    }

    process {
        $msgBytes = [System.Text.Encoding]::UTF8.GetBytes($InputObject)
        $nonce    = [byte[]]::new([PSSodium.Sodium]::NonceBytes)
        [PSSodium.Sodium]::randombytes_buf($nonce, [UIntPtr]::new([PSSodium.Sodium]::NonceBytes))

        $ciphertext = [byte[]]::new($msgBytes.Length + [PSSodium.Sodium]::MacBytes)
        $rc = [PSSodium.Sodium]::crypto_secretbox_easy(
            $ciphertext, $msgBytes, [ulong]$msgBytes.Length, $nonce, $keyBytes)
        if ($rc -ne 0) {
            $PSCmdlet.ThrowTerminatingError(
                [System.Management.Automation.ErrorRecord]::new(
                    [System.Exception]::new("crypto_secretbox_easy failed (rc=$rc)"),
                    'SodiumEncryptFailed',
                    [System.Management.Automation.ErrorCategory]::InvalidResult,
                    $InputObject))
        }

        $combined = [byte[]]::new($nonce.Length + $ciphertext.Length)
        [System.Buffer]::BlockCopy($nonce,      0, $combined, 0,             $nonce.Length)
        [System.Buffer]::BlockCopy($ciphertext, 0, $combined, $nonce.Length, $ciphertext.Length)

        [System.Convert]::ToBase64String($combined)
    }
}