// 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 string decodeMap [256]byte padChar rune } // Alphabet returns the Base32 alphabet used func ( *Encoding) () string { return .encode } const ( StdPadding rune = '=' NoPadding rune = -1 ) 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 { := new(Encoding) .padChar = StdPadding .encode = for := 0; < len(.decodeMap); ++ { .decodeMap[] = 0xFF } for := 0; < len(); ++ { .decodeMap[[]] = byte() } return } // NewEncoding returns a new case insensitive Encoding defined by the // given alphabet, which must be a 32-byte string. func ( string) *Encoding { := new(Encoding) .padChar = StdPadding .encode = for := 0; < len(.decodeMap); ++ { .decodeMap[] = 0xFF } for := 0; < len(); ++ { .decodeMap[asciiToLower([])] = byte() .decodeMap[asciiToUpper([])] = byte() } return } func asciiToLower( byte) byte { if >= 'A' && <= 'Z' { return + 32 } return } func asciiToUpper( byte) byte { if >= 'a' && <= 'z' { return - 32 } return } // WithPadding creates a new encoding identical to enc except // with a specified padding character, or NoPadding to disable padding. func ( Encoding) ( rune) *Encoding { .padChar = return & } // StdEncoding is the standard base32 encoding, as defined in // RFC 4648. var StdEncoding = NewEncodingCI(encodeStd) // HexEncoding is the “Extended Hex Alphabet” defined in RFC 4648. // It is typically used in DNS. var HexEncoding = NewEncodingCI(encodeHex) var RawStdEncoding = NewEncodingCI(encodeStd).WithPadding(NoPadding) var RawHexEncoding = NewEncodingCI(encodeHex).WithPadding(NoPadding) /* * 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) { if len() == 0 { return } // Unpack 8x 5-bit source blocks into a 5 byte // destination quantum for len() > 4 { [7] = .encode[[4]&0x1F] [6] = .encode[([4]>>5)|([3]<<3)&0x1F] [5] = .encode[([3]>>2)&0x1F] [4] = .encode[([3]>>7)|([2]<<1)&0x1F] [3] = .encode[(([2]>>4)|([1]<<4))&0x1F] [2] = .encode[([1]>>1)&0x1F] [1] = .encode[(([1]>>6)|([0]<<2))&0x1F] [0] = .encode[[0]>>3] = [5:] = [8:] } var byte switch len() { case 4: [6] = .encode[([3]<<3)&0x1F] [5] = .encode[([3]>>2)&0x1F] = [3] >> 7 fallthrough case 3: [4] = .encode[|([2]<<1)&0x1F] = ([2] >> 4) & 0x1F fallthrough case 2: [3] = .encode[|([1]<<4)&0x1F] [2] = .encode[([1]>>1)&0x1F] = ([1] >> 6) & 0x1F fallthrough case 1: [1] = .encode[|([0]<<2)&0x1F] [0] = .encode[[0]>>3] case 0: return } if .padChar != NoPadding { [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) } } } } } // 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. //lint:ignore S1001 fixed-length 5-byte slice 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]) .nbuf = 0 _, .err = .w.Write(.out[0:8]) } 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 // minimum # chars at 5 bits per char } 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) { := len() for len() > 0 && ! { // Decode quantum using the base32 alphabet var [8]byte := 8 for := 0; < 8; { if len() == 0 { if .padChar != NoPadding { return , false, CorruptInputError( - len() - ) } = break } := [0] = [1:] if == byte(.padChar) && >= 2 && len() < 8 { if .padChar == NoPadding { return , false, CorruptInputError() } // 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 } if len() > 5 { = [5:] } switch { case 2: += 1 case 4: += 2 case 5: += 3 case 7: += 4 case 8: += 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) { // FIXME: if dst is the same as s use decodeInPlace := make([]byte, 0, len()) for , := range { if != '\r' && != '\n' { = append(, ) } } , _, = .decode(, ) return } func ( *Encoding) ( []byte) ( int, error) { := 0 for , := range { if == '\n' || == '\r' { continue } [] = ++ } , _, = .decode(, [:]) return } // DecodeString returns the bytes represented by the base32 string s. func ( *Encoding) ( string) ([]byte, error) { := []byte() , := .decodeInPlace() if != nil { return nil, } return [:], nil } 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 ( *decoder) ( []byte) ( int, error) { if .err != nil { return 0, .err } // Use leftover decoded output from last read. if len(.out) > 0 { = copy(, .out) .out = .out[:] return , nil } // Read a chunk. := len() / 5 * 8 if < 8 { = 8 } if > len(.buf) { = len(.buf) } , .err = io.ReadAtLeast(.r, .buf[.nbuf:], 8-.nbuf) .nbuf += if .nbuf < 8 { return 0, .err } // Decode chunk into p, or d.out and then p if p is too small. := .nbuf / 8 * 8 := .nbuf / 8 * 5 if > len() { , .end, .err = .enc.decode(.outbuf[0:], .buf[0:]) .out = .outbuf[0:] = copy(, .out) .out = .out[:] } else { , .end, .err = .enc.decode(, .buf[0:]) } .nbuf -= for := 0; < .nbuf; ++ { .buf[] = .buf[+] } if .err == nil { .err = } return , .err } type newlineFilteringReader struct { wrapped io.Reader } func ( *newlineFilteringReader) ( []byte) (int, error) { , := .wrapped.Read() for > 0 { := 0 for , := range [0:] { if != '\r' && != '\n' { if != { [] = } ++ } } if > 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 + 7) / 8 } return / 8 * 5 }