key.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package fernet
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "encoding/hex"
  6. "errors"
  7. "io"
  8. )
  9. var (
  10. errKeyLen = errors.New("fernet: key decodes to wrong size")
  11. errNoKeys = errors.New("fernet: no keys provided")
  12. )
  13. // Key represents a key.
  14. type Key [32]byte
  15. func (k *Key) cryptBytes() []byte {
  16. return k[len(k)/2:]
  17. }
  18. func (k *Key) signBytes() []byte {
  19. return k[:len(k)/2]
  20. }
  21. // Generate initializes k with pseudorandom data from package crypto/rand.
  22. func (k *Key) Generate() error {
  23. _, err := io.ReadFull(rand.Reader, k[:])
  24. return err
  25. }
  26. // Encode returns the URL-safe base64 encoding of k.
  27. func (k *Key) Encode() string {
  28. return encoding.EncodeToString(k[:])
  29. }
  30. // DecodeKey decodes a key from s and returns it. The key can be in
  31. // hexadecimal, standard base64, or URL-safe base64.
  32. func DecodeKey(s string) (*Key, error) {
  33. var b []byte
  34. var err error
  35. if s == "" {
  36. return nil, errors.New("empty key")
  37. }
  38. if len(s) == hex.EncodedLen(len(Key{})) {
  39. b, err = hex.DecodeString(s)
  40. } else {
  41. b, err = base64.StdEncoding.DecodeString(s)
  42. if err != nil {
  43. b, err = base64.URLEncoding.DecodeString(s)
  44. }
  45. }
  46. if err != nil {
  47. return nil, err
  48. }
  49. if len(b) != len(Key{}) {
  50. return nil, errKeyLen
  51. }
  52. k := new(Key)
  53. copy(k[:], b)
  54. return k, nil
  55. }
  56. // DecodeKeys decodes each element of a using DecodeKey and returns the
  57. // resulting keys. Requires at least one key.
  58. func DecodeKeys(a ...string) ([]*Key, error) {
  59. if len(a) == 0 {
  60. return nil, errNoKeys
  61. }
  62. var err error
  63. ks := make([]*Key, len(a))
  64. for i, s := range a {
  65. ks[i], err = DecodeKey(s)
  66. if err != nil {
  67. return nil, err
  68. }
  69. }
  70. return ks, nil
  71. }
  72. // MustDecodeKeys is like DecodeKeys, but panics if an error occurs.
  73. // It simplifies safe initialization of global variables holding
  74. // keys.
  75. func MustDecodeKeys(a ...string) []*Key {
  76. k, err := DecodeKeys(a...)
  77. if err != nil {
  78. panic(err)
  79. }
  80. return k
  81. }