// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package base32 implements base32 encoding as specified by RFC 4648.
package base32 import ( ) /* * Encodings */ // An Encoding is a radix 32 encoding/decoding scheme, defined by a // 32-character alphabet. The most common is the "base32" encoding // introduced for SASL GSSAPI and standardized in RFC 4648. // The alternate "base32hex" encoding is used in DNSSEC. type Encoding struct { encode [32]byte decodeMap [256]byte padChar rune } const ( StdPadding rune = '=' // Standard padding character NoPadding rune = -1 // No padding ) const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" const encodeHex = "0123456789ABCDEFGHIJKLMNOPQRSTUV" // NewEncoding returns a new Encoding defined by the given alphabet, // which must be a 32-byte string. func ( string) *Encoding { if len() != 32 { panic("encoding alphabet is not 32-bytes long") } := new(Encoding) copy(.encode[:], ) .padChar = StdPadding for := 0; < len(.decodeMap); ++ { .decodeMap[] = 0xFF } for := 0; < len(); ++ { .decodeMap[[]] = byte() } return } // StdEncoding is the standard base32 encoding, as defined in // RFC 4648. var StdEncoding = NewEncoding(encodeStd) // HexEncoding is the ``Extended Hex Alphabet'' defined in RFC 4648. // It is typically used in DNS. var HexEncoding = NewEncoding(encodeHex) // WithPadding creates a new encoding identical to enc except // with a specified padding character, or NoPadding to disable padding. // The padding character must not be '\r' or '\n', must not // be contained in the encoding's alphabet and must be a rune equal or // below '\xff'. func ( Encoding) ( rune) *Encoding { if == '\r' || == '\n' || > 0xff { panic("invalid padding") } for := 0; < len(.encode); ++ { if rune(.encode[]) == { panic("padding contained in alphabet") } } .padChar = return & } /* * Encoder */ // Encode encodes src using the encoding enc, writing // EncodedLen(len(src)) bytes to dst. // // The encoding pads the output to a multiple of 8 bytes, // so Encode is not appropriate for use on individual blocks // of a large data stream. Use NewEncoder() instead. func ( *Encoding) (, []byte) { for len() > 0 { var [8]byte // Unpack 8x 5-bit source blocks into a 5 byte // destination quantum switch len() { default: [7] = [4] & 0x1F [6] = [4] >> 5 fallthrough case 4: [6] |= ([3] << 3) & 0x1F [5] = ([3] >> 2) & 0x1F [4] = [3] >> 7 fallthrough case 3: [4] |= ([2] << 1) & 0x1F [3] = ([2] >> 4) & 0x1F fallthrough case 2: [3] |= ([1] << 4) & 0x1F [2] = ([1] >> 1) & 0x1F [1] = ([1] >> 6) & 0x1F fallthrough case 1: [1] |= ([0] << 2) & 0x1F [0] = [0] >> 3 } // Encode 5-bit blocks using the base32 alphabet := len() if >= 8 { // Common case, unrolled for extra performance [0] = .encode[[0]&31] [1] = .encode[[1]&31] [2] = .encode[[2]&31] [3] = .encode[[3]&31] [4] = .encode[[4]&31] [5] = .encode[[5]&31] [6] = .encode[[6]&31] [7] = .encode[[7]&31] } else { for := 0; < ; ++ { [] = .encode[[]&31] } } // Pad the final quantum if len() < 5 { if .padChar == NoPadding { break } [7] = byte(.padChar) if len() < 4 { [6] = byte(.padChar) [5] = byte(.padChar) if len() < 3 { [4] = byte(.padChar) if len() < 2 { [3] = byte(.padChar) [2] = byte(.padChar) } } } break } = [5:] = [8:] } } // EncodeToString returns the base32 encoding of src. func ( *Encoding) ( []byte) string { := make([]byte, .EncodedLen(len())) .Encode(, ) return string() } type encoder struct { err error enc *Encoding w io.Writer buf [5]byte // buffered data waiting to be encoded nbuf int // number of bytes in buf out [1024]byte // output buffer } func ( *encoder) ( []byte) ( int, error) { if .err != nil { return 0, .err } // Leading fringe. if .nbuf > 0 { var int for = 0; < len() && .nbuf < 5; ++ { .buf[.nbuf] = [] .nbuf++ } += = [:] if .nbuf < 5 { return } .enc.Encode(.out[0:], .buf[0:]) if _, .err = .w.Write(.out[0:8]); .err != nil { return , .err } .nbuf = 0 } // Large interior chunks. for len() >= 5 { := len(.out) / 8 * 5 if > len() { = len() -= % 5 } .enc.Encode(.out[0:], [0:]) if _, .err = .w.Write(.out[0 : /5*8]); .err != nil { return , .err } += = [:] } // Trailing fringe. for := 0; < len(); ++ { .buf[] = [] } .nbuf = len() += len() return } // Close flushes any pending output from the encoder. // It is an error to call Write after calling Close. func ( *encoder) () error { // If there's anything left in the buffer, flush it out if .err == nil && .nbuf > 0 { .enc.Encode(.out[0:], .buf[0:.nbuf]) := .enc.EncodedLen(.nbuf) .nbuf = 0 _, .err = .w.Write(.out[0:]) } return .err } // NewEncoder returns a new base32 stream encoder. Data written to // the returned writer will be encoded using enc and then written to w. // Base32 encodings operate in 5-byte blocks; when finished // writing, the caller must Close the returned encoder to flush any // partially written blocks. func ( *Encoding, io.Writer) io.WriteCloser { return &encoder{enc: , w: } } // EncodedLen returns the length in bytes of the base32 encoding // of an input buffer of length n. func ( *Encoding) ( int) int { if .padChar == NoPadding { return (*8 + 4) / 5 } return ( + 4) / 5 * 8 } /* * Decoder */ type CorruptInputError int64 func ( CorruptInputError) () string { return "illegal base32 data at input byte " + strconv.FormatInt(int64(), 10) } // decode is like Decode but returns an additional 'end' value, which // indicates if end-of-message padding was encountered and thus any // additional data is an error. This method assumes that src has been // stripped of all supported whitespace ('\r' and '\n'). func ( *Encoding) (, []byte) ( int, bool, error) { // Lift the nil check outside of the loop. _ = .decodeMap := 0 := len() for len() > 0 && ! { // Decode quantum using the base32 alphabet var [8]byte := 8 for := 0; < 8; { if len() == 0 { if .padChar != NoPadding { // We have reached the end and are missing padding return , false, CorruptInputError( - len() - ) } // We have reached the end and are not expecting any padding , = , true break } := [0] = [1:] if == byte(.padChar) && >= 2 && len() < 8 { // We've reached the end and there's padding if len()+ < 8-1 { // not enough padding return , false, CorruptInputError() } for := 0; < 8-1-; ++ { if len() > && [] != byte(.padChar) { // incorrect padding return , false, CorruptInputError( - len() + - 1) } } , = , true // 7, 5 and 2 are not valid padding lengths, and so 1, 3 and 6 are not // valid dlen values. See RFC 4648 Section 6 "Base 32 Encoding" listing // the five valid padding lengths, and Section 9 "Illustrations and // Examples" for an illustration for how the 1st, 3rd and 6th base32 // src bytes do not yield enough information to decode a dst byte. if == 1 || == 3 || == 6 { return , false, CorruptInputError( - len() - 1) } break } [] = .decodeMap[] if [] == 0xFF { return , false, CorruptInputError( - len() - 1) } ++ } // Pack 8x 5-bit source blocks into 5 byte destination // quantum switch { case 8: [+4] = [6]<<5 | [7] ++ fallthrough case 7: [+3] = [4]<<7 | [5]<<2 | [6]>>3 ++ fallthrough case 5: [+2] = [3]<<4 | [4]>>1 ++ fallthrough case 4: [+1] = [1]<<6 | [2]<<1 | [3]>>4 ++ fallthrough case 2: [+0] = [0]<<3 | [1]>>2 ++ } += 5 } return , , nil } // Decode decodes src using the encoding enc. It writes at most // DecodedLen(len(src)) bytes to dst and returns the number of bytes // written. If src contains invalid base32 data, it will return the // number of bytes successfully written and CorruptInputError. // New line characters (\r and \n) are ignored. func ( *Encoding) (, []byte) ( int, error) { := make([]byte, len()) := stripNewlines(, ) , _, = .decode(, [:]) return } // DecodeString returns the bytes represented by the base32 string s. func ( *Encoding) ( string) ([]byte, error) { := []byte() := stripNewlines(, ) , , := .decode(, [:]) return [:], } type decoder struct { err error enc *Encoding r io.Reader end bool // saw end of message buf [1024]byte // leftover input nbuf int out []byte // leftover decoded output outbuf [1024 / 8 * 5]byte } func readEncodedData( io.Reader, []byte, int, bool) ( int, error) { for < && == nil { var int , = .Read([:]) += } // data was read, less than min bytes could be read if < && > 0 && == io.EOF { = io.ErrUnexpectedEOF } // no data was read, the buffer already contains some data // when padding is disabled this is not an error, as the message can be of // any length if && < 8 && == 0 && == io.EOF { = io.ErrUnexpectedEOF } return } func ( *decoder) ( []byte) ( int, error) { // Use leftover decoded output from last read. if len(.out) > 0 { = copy(, .out) .out = .out[:] if len(.out) == 0 { return , .err } return , nil } if .err != nil { return 0, .err } // Read a chunk. := len() / 5 * 8 if < 8 { = 8 } if > len(.buf) { = len(.buf) } // Minimum amount of bytes that needs to be read each cycle var int var bool if .enc.padChar == NoPadding { = 1 = false } else { = 8 - .nbuf = true } , .err = readEncodedData(.r, .buf[.nbuf:], , ) .nbuf += if .nbuf < { return 0, .err } // Decode chunk into p, or d.out and then p if p is too small. var int if .enc.padChar == NoPadding { = .nbuf } else { = .nbuf / 8 * 8 } := .enc.DecodedLen(.nbuf) if > len() { , .end, = .enc.decode(.outbuf[0:], .buf[0:]) .out = .outbuf[0:] = copy(, .out) .out = .out[:] } else { , .end, = .enc.decode(, .buf[0:]) } .nbuf -= for := 0; < .nbuf; ++ { .buf[] = .buf[+] } if != nil && (.err == nil || .err == io.EOF) { .err = } if len(.out) > 0 { // We cannot return all the decoded bytes to the caller in this // invocation of Read, so we return a nil error to ensure that Read // will be called again. The error stored in d.err, if any, will be // returned with the last set of decoded bytes. return , nil } return , .err } type newlineFilteringReader struct { wrapped io.Reader } // stripNewlines removes newline characters and returns the number // of non-newline characters copied to dst. func stripNewlines(, []byte) int { := 0 for , := range { if == '\r' || == '\n' { continue } [] = ++ } return } func ( *newlineFilteringReader) ( []byte) (int, error) { , := .wrapped.Read() for > 0 { := [0:] := stripNewlines(, ) if != nil || > 0 { return , } // Previous buffer entirely whitespace, read again , = .wrapped.Read() } return , } // NewDecoder constructs a new base32 stream decoder. func ( *Encoding, io.Reader) io.Reader { return &decoder{enc: , r: &newlineFilteringReader{}} } // DecodedLen returns the maximum length in bytes of the decoded data // corresponding to n bytes of base32-encoded data. func ( *Encoding) ( int) int { if .padChar == NoPadding { return * 5 / 8 } return / 8 * 5 }