Base64 Encoding in F#

F# provides built-in support for base64 encoding/decoding.

open System
open System.Text

let main() =
    // Here's the string we'll encode/decode.
    let data = "abc123!?$*&()'-=@~"

    // F# supports both standard and URL-compatible
    // base64. Here's how to encode using the standard
    // encoder.
    let sEnc = Convert.ToBase64String(Encoding.UTF8.GetBytes(data))
    printfn "%s" sEnc

    // Decoding may return an error, which you can handle
    // using exception handling if you don't already know
    // the input to be well-formed.
    let sDec = 
        try
            let bytes = Convert.FromBase64String(sEnc)
            Encoding.UTF8.GetString(bytes)
        with
        | :? FormatException -> "Decoding failed"
    
    printfn "%s" sDec
    printfn ""

    // This encodes/decodes using a URL-compatible base64
    // format.
    let uEnc = 
        Convert.ToBase64String(Encoding.UTF8.GetBytes(data))
            .Replace('+', '-')
            .Replace('/', '_')
            .TrimEnd('=')
    
    printfn "%s" uEnc

    let uDec =
        try
            let padding = String.replicate ((4 - uEnc.Length % 4) % 4) "="
            let base64 = uEnc.Replace('-', '+').Replace('_', '/') + padding
            let bytes = Convert.FromBase64String(base64)
            Encoding.UTF8.GetString(bytes)
        with
        | :? FormatException -> "Decoding failed"
    
    printfn "%s" uDec

main()

The string encodes to slightly different values with the standard and URL base64 encoders (trailing = vs no padding) but they both decode to the original string as desired.

$ dotnet fsi base64-encoding.fsx
YWJjMTIzIT8kKiYoKSctPUB+
abc123!?$*&()'-=@~

YWJjMTIzIT8kKiYoKSctPUB-
abc123!?$*&()'-=@~

In F#, we use the System.Convert class for base64 encoding and decoding. The standard base64 encoding is straightforward, while the URL-safe version requires some additional string manipulation to replace characters and handle padding.

Note that F# uses exceptions for error handling, so we’ve wrapped the decoding operations in try-catch blocks to handle potential format errors.