std/base32
import std/base32 to use it. Source: src/std/base32.iyi at v0.18.0.
import std/base32::{Base32, Base32Hex, Base32Error} Base32.encode("foobar") # "MZXW6YTBOI======"
Base32.encode("foobar", padding: false) # "MZXW6YTBOI"
Base32.decode("mzxw6ytboi") # the six bytes, or a Base32Error
Base32Hex.encode("foobar") # "CPNMUOJ1E8======"What is encoded is a String, whose bytes are taken, or an Array(UInt8); what is decoded is an Array(UInt8), because a base32 text is most often a key (an otpauth:// secret, a DNSSEC NSEC3 hash in Base32hex), and a key is bytes and seldom UTF-8.
encode writes the upper-case alphabet, padded with = to a multiple of eight characters unless padding: false is asked for (section 3.2 lets a specification leave it out, and the Key URI format TOTP secrets are handed around in does). decode reads either case, and padding is optional, but where there is any it must be the whole of it: the text then a multiple of eight characters long and the last group closed by exactly the = its data characters leave over. What is not base32 is a Base32Error naming what and where, never bytes made up or dropped:
* a byte outside the alphabet (section 3.3: "MUST reject"), and that
includes whitespace and line breaks, which this does not skip;
* data after the padding;
* padding that is too short, too long, or closes no group;
* a last group of 1, 3 or 6 characters, which ends on no whole byte;
* a last character that sets bits past the data (section 3.5): "MB"
and "MA" would both be "`f`" if those bits were ignored, and a
decoder that ignores them lets one byte string have many encodings.
The sentence names the canonical character.Python's base64.b32decode agrees with the first four (with casefold=True for lower case, and the text padded) and ignores the fifth; the gate holds that line exactly.
A character at a time each way: the texts this is for are tens of bytes, and the word-at-a-time loops std/base64 needed for megabytes would be code nothing here measures.
Pure computation: no platform, no clock, no randomness.
Base32struct
RFC 4648 section 6, the alphabet authenticator secrets are written in.
pub struct Base32
def self.decode(text : String) : Array(UInt8) | Base32Error
def self.encode(data : String | Array(UInt8), padding : Bool = true) : String
def initialize
endBase32Errorstruct
What decode answers for a text that is not base32.
pub struct Base32Error
def initialize(message : String)
def to_s : String
endBase32Hexstruct
RFC 4648 section 7, the extended-hex alphabet: what DNSSEC's NSEC3 records (RFC 5155) write their hashed names in.
pub struct Base32Hex
def self.decode(text : String) : Array(UInt8) | Base32Error
def self.encode(data : String | Array(UInt8), padding : Bool = true) : String
def initialize
endError for Base32Errorimpl
impl Error for Base32Error
def message : String
end
Base32, RFC 4648 section 6, and Base32hex, section 7, written in iyi.