...

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

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

     1  // Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>
     2  // Copyright 2013, Jonas mg
     3  // All rights reserved.
     4  //
     5  // Use of this source code is governed by a BSD-style license
     6  // that can be found in the LICENSE file.
     7  
     8  package common
     9  
    10  import (
    11  	"crypto/rand"
    12  	"errors"
    13  	"strconv"
    14  )
    15  
    16  var (
    17  	ErrSaltPrefix = errors.New("invalid magic prefix")
    18  	ErrSaltFormat = errors.New("invalid salt format")
    19  	ErrSaltRounds = errors.New("invalid rounds")
    20  )
    21  
    22  // Salt represents a salt.
    23  type Salt struct {
    24  	MagicPrefix []byte
    25  
    26  	SaltLenMin int
    27  	SaltLenMax int
    28  
    29  	RoundsMin     int
    30  	RoundsMax     int
    31  	RoundsDefault int
    32  }
    33  
    34  func (s *Salt) Generate(length int) []byte {
    35  	if length > s.SaltLenMax {
    36  		length = s.SaltLenMax
    37  	} else if length < s.SaltLenMin {
    38  		length = s.SaltLenMin
    39  	}
    40  
    41  	saltLen := (length * 6 / 8)
    42  	if (length*6)%8 != 0 {
    43  		saltLen++
    44  	}
    45  	salt := make([]byte, saltLen)
    46  	_, err := rand.Read(salt)
    47  	if err != nil {
    48  		return []byte{}
    49  	}
    50  
    51  	out := make([]byte, len(s.MagicPrefix)+length)
    52  	copy(out, s.MagicPrefix)
    53  	copy(out[len(s.MagicPrefix):], Base64_24Bit(salt))
    54  	return out
    55  }
    56  
    57  func (s *Salt) GenerateWRounds(length, rounds int) []byte {
    58  	if length > s.SaltLenMax {
    59  		length = s.SaltLenMax
    60  	} else if length < s.SaltLenMin {
    61  		length = s.SaltLenMin
    62  	}
    63  	if rounds < 0 {
    64  		rounds = s.RoundsDefault
    65  	} else if rounds < s.RoundsMin {
    66  		rounds = s.RoundsMin
    67  	} else if rounds > s.RoundsMax {
    68  		rounds = s.RoundsMax
    69  	}
    70  
    71  	saltLen := (length * 6 / 8)
    72  	if (length*6)%8 != 0 {
    73  		saltLen++
    74  	}
    75  	salt := make([]byte, saltLen)
    76  	_, err := rand.Read(salt)
    77  	if err != nil {
    78  		return []byte{}
    79  	}
    80  
    81  	roundsText := ""
    82  	if rounds != s.RoundsDefault {
    83  		roundsText = "rounds=" + strconv.Itoa(rounds) + "$"
    84  	}
    85  
    86  	out := make([]byte, len(s.MagicPrefix)+len(roundsText)+length)
    87  	copy(out, s.MagicPrefix)
    88  	copy(out[len(s.MagicPrefix):], []byte(roundsText))
    89  	copy(out[len(s.MagicPrefix)+len(roundsText):], Base64_24Bit(salt))
    90  	return out
    91  }
    92  

View as plain text