crypt.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Copyright 2013, Jonas mg
  2. // All rights reserved.
  3. //
  4. // Use of this source code is governed by a BSD-style license
  5. // that can be found in the LICENSE file.
  6. // Package crypt provides interface for password crypt functions and collects
  7. // common constants.
  8. package crypt
  9. import (
  10. "errors"
  11. "strings"
  12. "github.com/tredoe/osutil/user/crypt/common"
  13. )
  14. var ErrKeyMismatch = errors.New("hashed value is not the hash of the given password")
  15. // Crypter is the common interface implemented by all crypt functions.
  16. type Crypter interface {
  17. // Generate performs the hashing algorithm, returning a full hash suitable
  18. // for storage and later password verification.
  19. //
  20. // If the salt is empty, a randomly-generated salt will be generated with a
  21. // length of SaltLenMax and number RoundsDefault of rounds.
  22. //
  23. // Any error only can be got when the salt argument is not empty.
  24. Generate(key, salt []byte) (string, error)
  25. // Verify compares a hashed key with its possible key equivalent.
  26. // Returns nil on success, or an error on failure; if the hashed key is
  27. // diffrent, the error is "ErrKeyMismatch".
  28. Verify(hashedKey string, key []byte) error
  29. // Cost returns the hashing cost (in rounds) used to create the given hashed
  30. // key.
  31. //
  32. // When, in the future, the hashing cost of a key needs to be increased in
  33. // order to adjust for greater computational power, this function allows one
  34. // to establish which keys need to be updated.
  35. //
  36. // The algorithms based in MD5-crypt use a fixed value of rounds.
  37. Cost(hashedKey string) (int, error)
  38. // SetSalt sets a different salt. It is used to easily create derivated
  39. // algorithms, i.e. "apr1_crypt" from "md5_crypt".
  40. SetSalt(salt common.Salt)
  41. }
  42. // Crypt identifies a crypt function that is implemented in another package.
  43. type Crypt uint
  44. const (
  45. APR1 Crypt = iota + 1 // import "github.com/tredoe/osutil/user/crypt/apr1_crypt"
  46. MD5 // import "github.com/tredoe/osutil/user/crypt/md5_crypt"
  47. SHA256 // import "github.com/tredoe/osutil/user/crypt/sha256_crypt"
  48. SHA512 // import "github.com/tredoe/osutil/user/crypt/sha512_crypt"
  49. maxCrypt
  50. )
  51. var cryptPrefixes = make([]string, maxCrypt)
  52. var crypts = make([]func() Crypter, maxCrypt)
  53. // RegisterCrypt registers a function that returns a new instance of the given
  54. // crypt function. This is intended to be called from the init function in
  55. // packages that implement crypt functions.
  56. func RegisterCrypt(c Crypt, f func() Crypter, prefix string) {
  57. if c >= maxCrypt {
  58. panic("crypt: RegisterHash of unknown crypt function")
  59. }
  60. crypts[c] = f
  61. cryptPrefixes[c] = prefix
  62. }
  63. // New returns a new crypter.
  64. func New(c Crypt) Crypter {
  65. f := crypts[c]
  66. if f != nil {
  67. return f()
  68. }
  69. panic("crypt: requested crypt function is unavailable")
  70. }
  71. // NewFromHash returns a new Crypter using the prefix in the given hashed key.
  72. func NewFromHash(hashedKey string) Crypter {
  73. var f func() Crypter
  74. if strings.HasPrefix(hashedKey, cryptPrefixes[SHA512]) {
  75. f = crypts[SHA512]
  76. } else if strings.HasPrefix(hashedKey, cryptPrefixes[SHA256]) {
  77. f = crypts[SHA256]
  78. } else if strings.HasPrefix(hashedKey, cryptPrefixes[MD5]) {
  79. f = crypts[MD5]
  80. } else if strings.HasPrefix(hashedKey, cryptPrefixes[APR1]) {
  81. f = crypts[APR1]
  82. } else {
  83. toks := strings.SplitN(hashedKey, "$", 3)
  84. prefix := "$" + toks[1] + "$"
  85. panic("crypt: unknown cryp function from prefix: " + prefix)
  86. }
  87. if f != nil {
  88. return f()
  89. }
  90. panic("crypt: requested cryp function is unavailable")
  91. }