package jwt import ( "encoding/base64" "fmt" ) // Base64EncodedBufferLen return the size needed to encode the // Base64Encode (padding '=' would be added, can be stripped with // Base64DecodedStrippedLen func Base64EncodedBufferLen(n int) int { return base64.URLEncoding.EncodedLen(n) } // Base64EncodedStrippedLen return the size of the encoded slice with no // padding. func Base64EncodedStrippedLen(n int) int { eN := Base64EncodedBufferLen(n) mod := n % 3 if mod == 0 { return eN } return eN - (3 - mod) } // Base64DecodedStrippedLen returns the size of the data, without 0 // bit padding, from the stripped length n. func Base64DecodedStrippedLen(n int) int { return Base64DecodedLenFromStripped(n) + n - ((n+3)/4)*4 } // Base64DecodedLenFromStripped returns the size of the data, with 0 // bit padding, from the stripped length n. func Base64DecodedLenFromStripped(n int) int { return base64.URLEncoding.DecodedLen(4 * ((n + 3) / 4)) } // Base64Decode decodes a payload of data as a []byte, from a stripped // '=' encoded string. func Base64Decode(dst, src []byte) error { switch len(src) % 4 { // in this case, we have to copy the src, in order to allow decode part of the input case 2: oldSrc := src src = make([]byte, len(src)+2) copy(src, oldSrc) src[len(src)-2] = '=' src[len(src)-1] = '=' case 3: oldSrc := src src = make([]byte, len(src)+1) copy(src, oldSrc) src[len(src)-1] = '=' case 1: return fmt.Errorf("jwt: Invalid base64 string (length:%d %% 4 == 1): '%s'", len(src), src) } _, err := base64.URLEncoding.Decode(dst, src) if err != nil { return fmt.Errorf("jwt: %s", err) } return nil }