You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

647 lines
19 KiB

  1. // Copyright 2012 The Gorilla Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package securecookie
  5. import (
  6. "bytes"
  7. "crypto/aes"
  8. "crypto/cipher"
  9. "crypto/hmac"
  10. "crypto/rand"
  11. "crypto/sha256"
  12. "crypto/subtle"
  13. "encoding/base64"
  14. "encoding/gob"
  15. "encoding/json"
  16. "fmt"
  17. "hash"
  18. "io"
  19. "strconv"
  20. "strings"
  21. "time"
  22. )
  23. // Error is the interface of all errors returned by functions in this library.
  24. type Error interface {
  25. error
  26. // IsUsage returns true for errors indicating the client code probably
  27. // uses this library incorrectly. For example, the client may have
  28. // failed to provide a valid hash key, or may have failed to configure
  29. // the Serializer adequately for encoding value.
  30. IsUsage() bool
  31. // IsDecode returns true for errors indicating that a cookie could not
  32. // be decoded and validated. Since cookies are usually untrusted
  33. // user-provided input, errors of this type should be expected.
  34. // Usually, the proper action is simply to reject the request.
  35. IsDecode() bool
  36. // IsInternal returns true for unexpected errors occurring in the
  37. // securecookie implementation.
  38. IsInternal() bool
  39. // Cause, if it returns a non-nil value, indicates that this error was
  40. // propagated from some underlying library. If this method returns nil,
  41. // this error was raised directly by this library.
  42. //
  43. // Cause is provided principally for debugging/logging purposes; it is
  44. // rare that application logic should perform meaningfully different
  45. // logic based on Cause. See, for example, the caveats described on
  46. // (MultiError).Cause().
  47. Cause() error
  48. }
  49. // errorType is a bitmask giving the error type(s) of an cookieError value.
  50. type errorType int
  51. const (
  52. usageError = errorType(1 << iota)
  53. decodeError
  54. internalError
  55. )
  56. type cookieError struct {
  57. typ errorType
  58. msg string
  59. cause error
  60. }
  61. func (e cookieError) IsUsage() bool { return (e.typ & usageError) != 0 }
  62. func (e cookieError) IsDecode() bool { return (e.typ & decodeError) != 0 }
  63. func (e cookieError) IsInternal() bool { return (e.typ & internalError) != 0 }
  64. func (e cookieError) Cause() error { return e.cause }
  65. func (e cookieError) Error() string {
  66. parts := []string{"securecookie: "}
  67. if e.msg == "" {
  68. parts = append(parts, "error")
  69. } else {
  70. parts = append(parts, e.msg)
  71. }
  72. if c := e.Cause(); c != nil {
  73. parts = append(parts, " - caused by: ", c.Error())
  74. }
  75. return strings.Join(parts, "")
  76. }
  77. var (
  78. errGeneratingIV = cookieError{typ: internalError, msg: "failed to generate random iv"}
  79. errNoCodecs = cookieError{typ: usageError, msg: "no codecs provided"}
  80. errHashKeyNotSet = cookieError{typ: usageError, msg: "hash key is not set"}
  81. errBlockKeyNotSet = cookieError{typ: usageError, msg: "block key is not set"}
  82. errEncodedValueTooLong = cookieError{typ: usageError, msg: "the value is too long"}
  83. errValueToDecodeTooLong = cookieError{typ: decodeError, msg: "the value is too long"}
  84. errTimestampInvalid = cookieError{typ: decodeError, msg: "invalid timestamp"}
  85. errTimestampTooNew = cookieError{typ: decodeError, msg: "timestamp is too new"}
  86. errTimestampExpired = cookieError{typ: decodeError, msg: "expired timestamp"}
  87. errDecryptionFailed = cookieError{typ: decodeError, msg: "the value could not be decrypted"}
  88. errValueNotByte = cookieError{typ: decodeError, msg: "value not a []byte."}
  89. // ErrMacInvalid indicates that cookie decoding failed because the HMAC
  90. // could not be extracted and verified. Direct use of this error
  91. // variable is deprecated; it is public only for legacy compatibility,
  92. // and may be privatized in the future, as it is rarely useful to
  93. // distinguish between this error and other Error implementations.
  94. ErrMacInvalid = cookieError{typ: decodeError, msg: "the value is not valid"}
  95. )
  96. // Codec defines an interface to encode and decode cookie values.
  97. type Codec interface {
  98. Encode(name string, value interface{}) (string, error)
  99. Decode(name, value string, dst interface{}) error
  100. }
  101. // New returns a new SecureCookie.
  102. //
  103. // hashKey is required, used to authenticate values using HMAC. Create it using
  104. // GenerateRandomKey(). It is recommended to use a key with 32 or 64 bytes.
  105. //
  106. // blockKey is optional, used to encrypt values. Create it using
  107. // GenerateRandomKey(). The key length must correspond to the block size
  108. // of the encryption algorithm. For AES, used by default, valid lengths are
  109. // 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
  110. // The default encoder used for cookie serialization is encoding/gob.
  111. //
  112. // Note that keys created using GenerateRandomKey() are not automatically
  113. // persisted. New keys will be created when the application is restarted, and
  114. // previously issued cookies will not be able to be decoded.
  115. func New(hashKey, blockKey []byte) *SecureCookie {
  116. s := &SecureCookie{
  117. hashKey: hashKey,
  118. blockKey: blockKey,
  119. hashFunc: sha256.New,
  120. maxAge: 86400 * 30,
  121. maxLength: 4096,
  122. sz: GobEncoder{},
  123. }
  124. if hashKey == nil {
  125. s.err = errHashKeyNotSet
  126. }
  127. if blockKey != nil {
  128. s.BlockFunc(aes.NewCipher)
  129. }
  130. return s
  131. }
  132. // SecureCookie encodes and decodes authenticated and optionally encrypted
  133. // cookie values.
  134. type SecureCookie struct {
  135. hashKey []byte
  136. hashFunc func() hash.Hash
  137. blockKey []byte
  138. block cipher.Block
  139. maxLength int
  140. maxAge int64
  141. minAge int64
  142. err error
  143. sz Serializer
  144. // For testing purposes, the function that returns the current timestamp.
  145. // If not set, it will use time.Now().UTC().Unix().
  146. timeFunc func() int64
  147. }
  148. // Serializer provides an interface for providing custom serializers for cookie
  149. // values.
  150. type Serializer interface {
  151. Serialize(src interface{}) ([]byte, error)
  152. Deserialize(src []byte, dst interface{}) error
  153. }
  154. // GobEncoder encodes cookie values using encoding/gob. This is the simplest
  155. // encoder and can handle complex types via gob.Register.
  156. type GobEncoder struct{}
  157. // JSONEncoder encodes cookie values using encoding/json. Users who wish to
  158. // encode complex types need to satisfy the json.Marshaller and
  159. // json.Unmarshaller interfaces.
  160. type JSONEncoder struct{}
  161. // NopEncoder does not encode cookie values, and instead simply accepts a []byte
  162. // (as an interface{}) and returns a []byte. This is particularly useful when
  163. // you encoding an object upstream and do not wish to re-encode it.
  164. type NopEncoder struct{}
  165. // MaxLength restricts the maximum length, in bytes, for the cookie value.
  166. //
  167. // Default is 4096, which is the maximum value accepted by Internet Explorer.
  168. func (s *SecureCookie) MaxLength(value int) *SecureCookie {
  169. s.maxLength = value
  170. return s
  171. }
  172. // MaxAge restricts the maximum age, in seconds, for the cookie value.
  173. //
  174. // Default is 86400 * 30. Set it to 0 for no restriction.
  175. func (s *SecureCookie) MaxAge(value int) *SecureCookie {
  176. s.maxAge = int64(value)
  177. return s
  178. }
  179. // MinAge restricts the minimum age, in seconds, for the cookie value.
  180. //
  181. // Default is 0 (no restriction).
  182. func (s *SecureCookie) MinAge(value int) *SecureCookie {
  183. s.minAge = int64(value)
  184. return s
  185. }
  186. // HashFunc sets the hash function used to create HMAC.
  187. //
  188. // Default is crypto/sha256.New.
  189. func (s *SecureCookie) HashFunc(f func() hash.Hash) *SecureCookie {
  190. s.hashFunc = f
  191. return s
  192. }
  193. // BlockFunc sets the encryption function used to create a cipher.Block.
  194. //
  195. // Default is crypto/aes.New.
  196. func (s *SecureCookie) BlockFunc(f func([]byte) (cipher.Block, error)) *SecureCookie {
  197. if s.blockKey == nil {
  198. s.err = errBlockKeyNotSet
  199. } else if block, err := f(s.blockKey); err == nil {
  200. s.block = block
  201. } else {
  202. s.err = cookieError{cause: err, typ: usageError}
  203. }
  204. return s
  205. }
  206. // Encoding sets the encoding/serialization method for cookies.
  207. //
  208. // Default is encoding/gob. To encode special structures using encoding/gob,
  209. // they must be registered first using gob.Register().
  210. func (s *SecureCookie) SetSerializer(sz Serializer) *SecureCookie {
  211. s.sz = sz
  212. return s
  213. }
  214. // Encode encodes a cookie value.
  215. //
  216. // It serializes, optionally encrypts, signs with a message authentication code,
  217. // and finally encodes the value.
  218. //
  219. // The name argument is the cookie name. It is stored with the encoded value.
  220. // The value argument is the value to be encoded. It can be any value that can
  221. // be encoded using the currently selected serializer; see SetSerializer().
  222. //
  223. // It is the client's responsibility to ensure that value, when encoded using
  224. // the current serialization/encryption settings on s and then base64-encoded,
  225. // is shorter than the maximum permissible length.
  226. func (s *SecureCookie) Encode(name string, value interface{}) (string, error) {
  227. if s.err != nil {
  228. return "", s.err
  229. }
  230. if s.hashKey == nil {
  231. s.err = errHashKeyNotSet
  232. return "", s.err
  233. }
  234. var err error
  235. var b []byte
  236. // 1. Serialize.
  237. if b, err = s.sz.Serialize(value); err != nil {
  238. return "", cookieError{cause: err, typ: usageError}
  239. }
  240. // 2. Encrypt (optional).
  241. if s.block != nil {
  242. if b, err = encrypt(s.block, b); err != nil {
  243. return "", cookieError{cause: err, typ: usageError}
  244. }
  245. }
  246. b = encode(b)
  247. // 3. Create MAC for "name|date|value". Extra pipe to be used later.
  248. b = []byte(fmt.Sprintf("%s|%d|%s|", name, s.timestamp(), b))
  249. mac := createMac(hmac.New(s.hashFunc, s.hashKey), b[:len(b)-1])
  250. // Append mac, remove name.
  251. b = append(b, mac...)[len(name)+1:]
  252. // 4. Encode to base64.
  253. b = encode(b)
  254. // 5. Check length.
  255. if s.maxLength != 0 && len(b) > s.maxLength {
  256. return "", errEncodedValueTooLong
  257. }
  258. // Done.
  259. return string(b), nil
  260. }
  261. // Decode decodes a cookie value.
  262. //
  263. // It decodes, verifies a message authentication code, optionally decrypts and
  264. // finally deserializes the value.
  265. //
  266. // The name argument is the cookie name. It must be the same name used when
  267. // it was stored. The value argument is the encoded cookie value. The dst
  268. // argument is where the cookie will be decoded. It must be a pointer.
  269. func (s *SecureCookie) Decode(name, value string, dst interface{}) error {
  270. if s.err != nil {
  271. return s.err
  272. }
  273. if s.hashKey == nil {
  274. s.err = errHashKeyNotSet
  275. return s.err
  276. }
  277. // 1. Check length.
  278. if s.maxLength != 0 && len(value) > s.maxLength {
  279. return errValueToDecodeTooLong
  280. }
  281. // 2. Decode from base64.
  282. b, err := decode([]byte(value))
  283. if err != nil {
  284. return err
  285. }
  286. // 3. Verify MAC. Value is "date|value|mac".
  287. parts := bytes.SplitN(b, []byte("|"), 3)
  288. if len(parts) != 3 {
  289. return ErrMacInvalid
  290. }
  291. h := hmac.New(s.hashFunc, s.hashKey)
  292. b = append([]byte(name+"|"), b[:len(b)-len(parts[2])-1]...)
  293. if err = verifyMac(h, b, parts[2]); err != nil {
  294. return err
  295. }
  296. // 4. Verify date ranges.
  297. var t1 int64
  298. if t1, err = strconv.ParseInt(string(parts[0]), 10, 64); err != nil {
  299. return errTimestampInvalid
  300. }
  301. t2 := s.timestamp()
  302. if s.minAge != 0 && t1 > t2-s.minAge {
  303. return errTimestampTooNew
  304. }
  305. if s.maxAge != 0 && t1 < t2-s.maxAge {
  306. return errTimestampExpired
  307. }
  308. // 5. Decrypt (optional).
  309. b, err = decode(parts[1])
  310. if err != nil {
  311. return err
  312. }
  313. if s.block != nil {
  314. if b, err = decrypt(s.block, b); err != nil {
  315. return err
  316. }
  317. }
  318. // 6. Deserialize.
  319. if err = s.sz.Deserialize(b, dst); err != nil {
  320. return cookieError{cause: err, typ: decodeError}
  321. }
  322. // Done.
  323. return nil
  324. }
  325. // timestamp returns the current timestamp, in seconds.
  326. //
  327. // For testing purposes, the function that generates the timestamp can be
  328. // overridden. If not set, it will return time.Now().UTC().Unix().
  329. func (s *SecureCookie) timestamp() int64 {
  330. if s.timeFunc == nil {
  331. return time.Now().UTC().Unix()
  332. }
  333. return s.timeFunc()
  334. }
  335. // Authentication -------------------------------------------------------------
  336. // createMac creates a message authentication code (MAC).
  337. func createMac(h hash.Hash, value []byte) []byte {
  338. h.Write(value)
  339. return h.Sum(nil)
  340. }
  341. // verifyMac verifies that a message authentication code (MAC) is valid.
  342. func verifyMac(h hash.Hash, value []byte, mac []byte) error {
  343. mac2 := createMac(h, value)
  344. // Check that both MACs are of equal length, as subtle.ConstantTimeCompare
  345. // does not do this prior to Go 1.4.
  346. if len(mac) == len(mac2) && subtle.ConstantTimeCompare(mac, mac2) == 1 {
  347. return nil
  348. }
  349. return ErrMacInvalid
  350. }
  351. // Encryption -----------------------------------------------------------------
  352. // encrypt encrypts a value using the given block in counter mode.
  353. //
  354. // A random initialization vector (http://goo.gl/zF67k) with the length of the
  355. // block size is prepended to the resulting ciphertext.
  356. func encrypt(block cipher.Block, value []byte) ([]byte, error) {
  357. iv := GenerateRandomKey(block.BlockSize())
  358. if iv == nil {
  359. return nil, errGeneratingIV
  360. }
  361. // Encrypt it.
  362. stream := cipher.NewCTR(block, iv)
  363. stream.XORKeyStream(value, value)
  364. // Return iv + ciphertext.
  365. return append(iv, value...), nil
  366. }
  367. // decrypt decrypts a value using the given block in counter mode.
  368. //
  369. // The value to be decrypted must be prepended by a initialization vector
  370. // (http://goo.gl/zF67k) with the length of the block size.
  371. func decrypt(block cipher.Block, value []byte) ([]byte, error) {
  372. size := block.BlockSize()
  373. if len(value) > size {
  374. // Extract iv.
  375. iv := value[:size]
  376. // Extract ciphertext.
  377. value = value[size:]
  378. // Decrypt it.
  379. stream := cipher.NewCTR(block, iv)
  380. stream.XORKeyStream(value, value)
  381. return value, nil
  382. }
  383. return nil, errDecryptionFailed
  384. }
  385. // Serialization --------------------------------------------------------------
  386. // Serialize encodes a value using gob.
  387. func (e GobEncoder) Serialize(src interface{}) ([]byte, error) {
  388. buf := new(bytes.Buffer)
  389. enc := gob.NewEncoder(buf)
  390. if err := enc.Encode(src); err != nil {
  391. return nil, cookieError{cause: err, typ: usageError}
  392. }
  393. return buf.Bytes(), nil
  394. }
  395. // Deserialize decodes a value using gob.
  396. func (e GobEncoder) Deserialize(src []byte, dst interface{}) error {
  397. dec := gob.NewDecoder(bytes.NewBuffer(src))
  398. if err := dec.Decode(dst); err != nil {
  399. return cookieError{cause: err, typ: decodeError}
  400. }
  401. return nil
  402. }
  403. // Serialize encodes a value using encoding/json.
  404. func (e JSONEncoder) Serialize(src interface{}) ([]byte, error) {
  405. buf := new(bytes.Buffer)
  406. enc := json.NewEncoder(buf)
  407. if err := enc.Encode(src); err != nil {
  408. return nil, cookieError{cause: err, typ: usageError}
  409. }
  410. return buf.Bytes(), nil
  411. }
  412. // Deserialize decodes a value using encoding/json.
  413. func (e JSONEncoder) Deserialize(src []byte, dst interface{}) error {
  414. dec := json.NewDecoder(bytes.NewReader(src))
  415. if err := dec.Decode(dst); err != nil {
  416. return cookieError{cause: err, typ: decodeError}
  417. }
  418. return nil
  419. }
  420. // Serialize passes a []byte through as-is.
  421. func (e NopEncoder) Serialize(src interface{}) ([]byte, error) {
  422. if b, ok := src.([]byte); ok {
  423. return b, nil
  424. }
  425. return nil, errValueNotByte
  426. }
  427. // Deserialize passes a []byte through as-is.
  428. func (e NopEncoder) Deserialize(src []byte, dst interface{}) error {
  429. if _, ok := dst.([]byte); ok {
  430. dst = src
  431. return nil
  432. }
  433. return errValueNotByte
  434. }
  435. // Encoding -------------------------------------------------------------------
  436. // encode encodes a value using base64.
  437. func encode(value []byte) []byte {
  438. encoded := make([]byte, base64.URLEncoding.EncodedLen(len(value)))
  439. base64.URLEncoding.Encode(encoded, value)
  440. return encoded
  441. }
  442. // decode decodes a cookie using base64.
  443. func decode(value []byte) ([]byte, error) {
  444. decoded := make([]byte, base64.URLEncoding.DecodedLen(len(value)))
  445. b, err := base64.URLEncoding.Decode(decoded, value)
  446. if err != nil {
  447. return nil, cookieError{cause: err, typ: decodeError, msg: "base64 decode failed"}
  448. }
  449. return decoded[:b], nil
  450. }
  451. // Helpers --------------------------------------------------------------------
  452. // GenerateRandomKey creates a random key with the given length in bytes.
  453. // On failure, returns nil.
  454. //
  455. // Callers should explicitly check for the possibility of a nil return, treat
  456. // it as a failure of the system random number generator, and not continue.
  457. func GenerateRandomKey(length int) []byte {
  458. k := make([]byte, length)
  459. if _, err := io.ReadFull(rand.Reader, k); err != nil {
  460. return nil
  461. }
  462. return k
  463. }
  464. // CodecsFromPairs returns a slice of SecureCookie instances.
  465. //
  466. // It is a convenience function to create a list of codecs for key rotation. Note
  467. // that the generated Codecs will have the default options applied: callers
  468. // should iterate over each Codec and type-assert the underlying *SecureCookie to
  469. // change these.
  470. //
  471. // Example:
  472. //
  473. // codecs := securecookie.CodecsFromPairs(
  474. // []byte("new-hash-key"),
  475. // []byte("new-block-key"),
  476. // []byte("old-hash-key"),
  477. // []byte("old-block-key"),
  478. // )
  479. //
  480. // // Modify each instance.
  481. // for _, s := range codecs {
  482. // if cookie, ok := s.(*securecookie.SecureCookie); ok {
  483. // cookie.MaxAge(86400 * 7)
  484. // cookie.SetSerializer(securecookie.JSONEncoder{})
  485. // cookie.HashFunc(sha512.New512_256)
  486. // }
  487. // }
  488. //
  489. func CodecsFromPairs(keyPairs ...[]byte) []Codec {
  490. codecs := make([]Codec, len(keyPairs)/2+len(keyPairs)%2)
  491. for i := 0; i < len(keyPairs); i += 2 {
  492. var blockKey []byte
  493. if i+1 < len(keyPairs) {
  494. blockKey = keyPairs[i+1]
  495. }
  496. codecs[i/2] = New(keyPairs[i], blockKey)
  497. }
  498. return codecs
  499. }
  500. // EncodeMulti encodes a cookie value using a group of codecs.
  501. //
  502. // The codecs are tried in order. Multiple codecs are accepted to allow
  503. // key rotation.
  504. //
  505. // On error, may return a MultiError.
  506. func EncodeMulti(name string, value interface{}, codecs ...Codec) (string, error) {
  507. if len(codecs) == 0 {
  508. return "", errNoCodecs
  509. }
  510. var errors MultiError
  511. for _, codec := range codecs {
  512. encoded, err := codec.Encode(name, value)
  513. if err == nil {
  514. return encoded, nil
  515. }
  516. errors = append(errors, err)
  517. }
  518. return "", errors
  519. }
  520. // DecodeMulti decodes a cookie value using a group of codecs.
  521. //
  522. // The codecs are tried in order. Multiple codecs are accepted to allow
  523. // key rotation.
  524. //
  525. // On error, may return a MultiError.
  526. func DecodeMulti(name string, value string, dst interface{}, codecs ...Codec) error {
  527. if len(codecs) == 0 {
  528. return errNoCodecs
  529. }
  530. var errors MultiError
  531. for _, codec := range codecs {
  532. err := codec.Decode(name, value, dst)
  533. if err == nil {
  534. return nil
  535. }
  536. errors = append(errors, err)
  537. }
  538. return errors
  539. }
  540. // MultiError groups multiple errors.
  541. type MultiError []error
  542. func (m MultiError) IsUsage() bool { return m.any(func(e Error) bool { return e.IsUsage() }) }
  543. func (m MultiError) IsDecode() bool { return m.any(func(e Error) bool { return e.IsDecode() }) }
  544. func (m MultiError) IsInternal() bool { return m.any(func(e Error) bool { return e.IsInternal() }) }
  545. // Cause returns nil for MultiError; there is no unique underlying cause in the
  546. // general case.
  547. //
  548. // Note: we could conceivably return a non-nil Cause only when there is exactly
  549. // one child error with a Cause. However, it would be brittle for client code
  550. // to rely on the arity of causes inside a MultiError, so we have opted not to
  551. // provide this functionality. Clients which really wish to access the Causes
  552. // of the underlying errors are free to iterate through the errors themselves.
  553. func (m MultiError) Cause() error { return nil }
  554. func (m MultiError) Error() string {
  555. s, n := "", 0
  556. for _, e := range m {
  557. if e != nil {
  558. if n == 0 {
  559. s = e.Error()
  560. }
  561. n++
  562. }
  563. }
  564. switch n {
  565. case 0:
  566. return "(0 errors)"
  567. case 1:
  568. return s
  569. case 2:
  570. return s + " (and 1 other error)"
  571. }
  572. return fmt.Sprintf("%s (and %d other errors)", s, n-1)
  573. }
  574. // any returns true if any element of m is an Error for which pred returns true.
  575. func (m MultiError) any(pred func(Error) bool) bool {
  576. for _, e := range m {
  577. if ourErr, ok := e.(Error); ok && pred(ourErr) {
  578. return true
  579. }
  580. }
  581. return false
  582. }