...

Source file src/edge-infra.dev/pkg/lib/crypto/osutilcrypt/crypt.go

Documentation: edge-infra.dev/pkg/lib/crypto/osutilcrypt

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

View as plain text