15// SecretBytes attempts to base64 decode the secret, if that fails it treats the secret as binary
16func SecretBytes(secret string) []byte {
17 b, err := base64.RawURLEncoding.DecodeString(strings.TrimRight(secret, "="))
19 // Only return decoded form if a valid AES length
20 // Don't want unintentional decoding resulting in invalid lengths confusing a user
21 // that thought they used a 16, 24, 32 length string
22 for _, i := range []int{16, 24, 32} {
28 // If decoding didn't work or resulted in non-AES compliant length,
29 // assume the raw string was the intended secret
33// cookies are stored in a 3 part (value + timestamp + signature) to enforce that the values are as originally set.
34// additionally, the 'value' is encrypted so it's opaque to the browser
36// Validate ensures a cookie is properly signed
37func Validate(cookie *http.Cookie, seed string, expiration time.Duration) (value []byte, t time.Time, ok bool) {
38 // value, timestamp, sig
39 parts := strings.Split(cookie.Value, "|")
43 if checkSignature(parts[2], seed, cookie.Name, parts[0], parts[1]) {
44 ts, err := strconv.Atoi(parts[1])
48 // The expiration timestamp set when the cookie was created
49 // isn't sent back by the browser. Hence, we check whether the
50 // creation timestamp stored in the cookie falls within the
51 // window defined by (Now()-expiration, Now()].
52 t = time.Unix(int64(ts), 0)
53 if t.After(time.Now().Add(expiration*-1)) && t.Before(time.Now().Add(time.Minute*5)) {
54 // it's a valid cookie. now get the contents
55 rawValue, err := base64.URLEncoding.DecodeString(parts[0])
66// SignedValue returns a cookie that is signed and can later be checked with Validate
67func SignedValue(seed string, key string, value []byte, now time.Time) (string, error) {
68 encodedValue := base64.URLEncoding.EncodeToString(value)
69 timeStr := fmt.Sprintf("%d", now.Unix())
70 sig, err := cookieSignature(sha256.New, seed, key, encodedValue, timeStr)
74 cookieVal := fmt.Sprintf("%s|%s|%s", encodedValue, timeStr, sig)
78func cookieSignature(signer func() hash.Hash, args ...string) (string, error) {
79 h := hmac.New(signer, []byte(args[0]))
80 for _, arg := range args[1:] {
81 _, err := h.Write([]byte(arg))
88 return base64.URLEncoding.EncodeToString(b), nil
91func checkSignature(signature string, args ...string) bool {
92 checkSig, err := cookieSignature(sha256.New, args...)
96 return checkHmac(signature, checkSig)
99func checkHmac(input, expected string) bool {
100 inputMAC, err1 := base64.URLEncoding.DecodeString(input)
102 expectedMAC, err2 := base64.URLEncoding.DecodeString(expected)
104 return hmac.Equal(inputMAC, expectedMAC)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list