mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-02-07 04:41:31 -05:00
test(groupware): add testcontainers based jmap test
* adds pkg/jmap/jmap_integration_test.go
* uses ghcr.io/stalwartlabs/stalwart:v0.13.2-alpine
* can be disabled by setting one of the following environment
variables, in the same fashion as ca0493b28
- CI=woodpecker
- CI_SYSTEM_NAME=woodpecker
- USE_TESTCONTAINERS=false
* dependencies:
- bump github.com/go-test/deep from 1.1.0 to 1.1.1
- add github.com/cention-sany/utf7
- add github.com/dustinkirkland/golang-petname
- add github.com/emersion/go-imap/v2
- add github.com/emersion/go-message
- add github.com/emersion/go-sasl
- add github.com/go-crypt/crypt
- add github.com/go-crypt/x
- add github.com/gogs/chardet
- add github.com/inbucket/html2text
- add github.com/jhilleryerd/enmime/v2
- add github.com/ssor/bom
- add gopkg.in/loremipsum.v1
This commit is contained in:
26
vendor/github.com/go-crypt/crypt/algorithm/const.go
generated
vendored
Normal file
26
vendor/github.com/go-crypt/crypt/algorithm/const.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package algorithm
|
||||
|
||||
const (
|
||||
// DigestSHA1 is te name for SHA1 digests.
|
||||
DigestSHA1 = "sha1"
|
||||
|
||||
// DigestSHA224 is te name for SHA224 digests.
|
||||
DigestSHA224 = "sha224"
|
||||
|
||||
// DigestSHA256 is te name for SHA256 digests.
|
||||
DigestSHA256 = "sha256"
|
||||
|
||||
// DigestSHA384 is te name for SHA384 digests.
|
||||
DigestSHA384 = "sha384"
|
||||
|
||||
// DigestSHA512 is te name for SHA512 digests.
|
||||
DigestSHA512 = "sha512"
|
||||
)
|
||||
|
||||
const (
|
||||
// SaltLengthDefault is the default salt size for most implementations.
|
||||
SaltLengthDefault = 16
|
||||
|
||||
// KeyLengthDefault is the default key size for most implementations.
|
||||
KeyLengthDefault = 32
|
||||
)
|
||||
3
vendor/github.com/go-crypt/crypt/algorithm/doc.go
generated
vendored
Normal file
3
vendor/github.com/go-crypt/crypt/algorithm/doc.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package algorithm is a package which contains the individual algorithms and interfaces related to their
|
||||
// implementation.
|
||||
package algorithm
|
||||
66
vendor/github.com/go-crypt/crypt/algorithm/errors.go
generated
vendored
Normal file
66
vendor/github.com/go-crypt/crypt/algorithm/errors.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package algorithm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrEncodedHashInvalidFormat is an error returned when an encoded hash has an invalid format.
|
||||
ErrEncodedHashInvalidFormat = errors.New("provided encoded hash has an invalid format")
|
||||
|
||||
// ErrEncodedHashInvalidIdentifier is an error returned when an encoded hash has an invalid identifier for the
|
||||
// given digest.
|
||||
ErrEncodedHashInvalidIdentifier = errors.New("provided encoded hash has an invalid identifier")
|
||||
|
||||
// ErrEncodedHashInvalidVersion is an error returned when an encoded hash has an unsupported or otherwise invalid
|
||||
// version.
|
||||
ErrEncodedHashInvalidVersion = errors.New("provided encoded hash has an invalid version")
|
||||
|
||||
// ErrEncodedHashInvalidOption is an error returned when an encoded hash has an unsupported or otherwise invalid
|
||||
// option in the option field.
|
||||
ErrEncodedHashInvalidOption = errors.New("provided encoded hash has an invalid option")
|
||||
|
||||
// ErrEncodedHashInvalidOptionKey is an error returned when an encoded hash has an unknown or otherwise invalid
|
||||
// option key in the option field.
|
||||
ErrEncodedHashInvalidOptionKey = errors.New("provided encoded hash has an invalid option key")
|
||||
|
||||
// ErrEncodedHashInvalidOptionValue is an error returned when an encoded hash has an unknown or otherwise invalid
|
||||
// option value in the option field.
|
||||
ErrEncodedHashInvalidOptionValue = errors.New("provided encoded hash has an invalid option value")
|
||||
|
||||
// ErrEncodedHashKeyEncoding is an error returned when an encoded hash has a salt with an invalid or unsupported
|
||||
// encoding.
|
||||
ErrEncodedHashKeyEncoding = errors.New("provided encoded hash has a key value that can't be decoded")
|
||||
|
||||
// ErrEncodedHashSaltEncoding is an error returned when an encoded hash has a salt with an invalid or unsupported
|
||||
// encoding.
|
||||
ErrEncodedHashSaltEncoding = errors.New("provided encoded hash has a salt value that can't be decoded")
|
||||
|
||||
// ErrKeyDerivation is returned when a Key function returns an error.
|
||||
ErrKeyDerivation = errors.New("failed to derive the key with the provided parameters")
|
||||
|
||||
// ErrSaltEncoding is an error returned when a salt has an invalid or unsupported encoding.
|
||||
ErrSaltEncoding = errors.New("provided salt has a value that can't be decoded")
|
||||
|
||||
// ErrPasswordInvalid is an error returned when a password has an invalid or unsupported properties. It is NOT
|
||||
// returned on password mismatches.
|
||||
ErrPasswordInvalid = errors.New("password is invalid")
|
||||
|
||||
// ErrSaltInvalid is an error returned when a salt has an invalid or unsupported properties.
|
||||
ErrSaltInvalid = errors.New("salt is invalid")
|
||||
|
||||
// ErrSaltReadRandomBytes is an error returned when generating the random bytes for salt resulted in an error.
|
||||
ErrSaltReadRandomBytes = errors.New("could not read random bytes for salt")
|
||||
|
||||
// ErrParameterInvalid is an error returned when a parameter has an invalid value.
|
||||
ErrParameterInvalid = errors.New("parameter is invalid")
|
||||
)
|
||||
|
||||
// Error format strings.
|
||||
const (
|
||||
ErrFmtInvalidIntParameter = "%w: parameter '%s' must be between %d%s and %d but is set to '%d'"
|
||||
ErrFmtDigestDecode = "%s decode error: %w"
|
||||
ErrFmtDigestMatch = "%s match error: %w"
|
||||
ErrFmtHasherHash = "%s hashing error: %w"
|
||||
ErrFmtHasherValidation = "%s validation error: %w"
|
||||
)
|
||||
46
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/const.go
generated
vendored
Normal file
46
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/const.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package shacrypt
|
||||
|
||||
const (
|
||||
// EncodingFmt is the encoding format for this algorithm.
|
||||
EncodingFmt = "$%s$rounds=%d$%s$%s"
|
||||
|
||||
// EncodingFmtRoundsOmitted is the encoding format for this algorithm when the rounds can be omitted.
|
||||
EncodingFmtRoundsOmitted = "$%s$%s$%s"
|
||||
|
||||
// AlgName is the name for this algorithm.
|
||||
AlgName = "shacrypt"
|
||||
|
||||
// AlgIdentifierSHA256 is the identifier used in encoded SHA256 variants of this algorithm.
|
||||
AlgIdentifierSHA256 = "5"
|
||||
|
||||
// AlgIdentifierSHA512 is the identifier used in encoded SHA512 variants of this algorithm.
|
||||
AlgIdentifierSHA512 = "6"
|
||||
|
||||
// IterationsMin is the minimum number of iterations accepted.
|
||||
IterationsMin = 1000
|
||||
|
||||
// IterationsMax is the maximum number of iterations accepted.
|
||||
IterationsMax = 999999999
|
||||
|
||||
// IterationsDefaultSHA256 is the default number of iterations for SHA256.
|
||||
IterationsDefaultSHA256 = 1000000
|
||||
|
||||
// IterationsDefaultSHA512 is the default number of iterations for SHA512.
|
||||
IterationsDefaultSHA512 = 500000
|
||||
|
||||
// IterationsDefaultOmitted is the default number of iterations when the rounds are omitted.
|
||||
IterationsDefaultOmitted = 5000
|
||||
|
||||
// SaltLengthMin is the minimum salt length.
|
||||
SaltLengthMin = 1
|
||||
|
||||
// SaltLengthMax is the maximum salt length.
|
||||
SaltLengthMax = 16
|
||||
|
||||
// SaltCharSet are the valid characters for the salt.
|
||||
SaltCharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./"
|
||||
)
|
||||
|
||||
const (
|
||||
variantDefault = VariantSHA512
|
||||
)
|
||||
136
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/decoder.go
generated
vendored
Normal file
136
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/decoder.go
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
package shacrypt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-crypt/crypt/algorithm"
|
||||
"github.com/go-crypt/crypt/internal/encoding"
|
||||
)
|
||||
|
||||
// RegisterDecoder the decoder with the algorithm.DecoderRegister.
|
||||
func RegisterDecoder(r algorithm.DecoderRegister) (err error) {
|
||||
if err = RegisterDecoderSHA256(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = RegisterDecoderSHA512(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterDecoderSHA256 registers specifically the sha256 decoder variant with the algorithm.DecoderRegister.
|
||||
func RegisterDecoderSHA256(r algorithm.DecoderRegister) (err error) {
|
||||
if err = r.RegisterDecodeFunc(VariantSHA256.Prefix(), DecodeVariant(VariantSHA256)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterDecoderSHA512 registers specifically the sha512 decoder variant with the algorithm.DecoderRegister.
|
||||
func RegisterDecoderSHA512(r algorithm.DecoderRegister) (err error) {
|
||||
if err = r.RegisterDecodeFunc(VariantSHA512.Prefix(), DecodeVariant(VariantSHA512)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decode the encoded digest into a algorithm.Digest.
|
||||
func Decode(encodedDigest string) (digest algorithm.Digest, err error) {
|
||||
return DecodeVariant(VariantNone)(encodedDigest)
|
||||
}
|
||||
|
||||
// DecodeVariant the encoded digest into a algorithm.Digest provided it matches the provided Variant. If VariantNone is
|
||||
// used all variants can be decoded.
|
||||
func DecodeVariant(v Variant) func(encodedDigest string) (digest algorithm.Digest, err error) {
|
||||
return func(encodedDigest string) (digest algorithm.Digest, err error) {
|
||||
var (
|
||||
parts []string
|
||||
variant Variant
|
||||
)
|
||||
|
||||
if variant, parts, err = decoderParts(encodedDigest); err != nil {
|
||||
return nil, fmt.Errorf(algorithm.ErrFmtDigestDecode, AlgName, err)
|
||||
}
|
||||
|
||||
if v != VariantNone && v != variant {
|
||||
return nil, fmt.Errorf(algorithm.ErrFmtDigestDecode, AlgName, fmt.Errorf("the '%s' variant cannot be decoded only the '%s' variant can be", variant.String(), v.String()))
|
||||
}
|
||||
|
||||
if digest, err = decode(variant, parts); err != nil {
|
||||
return nil, fmt.Errorf(algorithm.ErrFmtDigestDecode, AlgName, err)
|
||||
}
|
||||
|
||||
return digest, nil
|
||||
}
|
||||
}
|
||||
|
||||
func decoderParts(encodedDigest string) (variant Variant, parts []string, err error) {
|
||||
parts = encoding.Split(encodedDigest, -1)
|
||||
|
||||
if n := len(parts); n != 4 && n != 5 {
|
||||
return VariantNone, nil, algorithm.ErrEncodedHashInvalidFormat
|
||||
}
|
||||
|
||||
variant = NewVariant(parts[1])
|
||||
|
||||
if variant == VariantNone {
|
||||
return variant, nil, fmt.Errorf("%w: identifier '%s' is not an encoded %s digest", algorithm.ErrEncodedHashInvalidIdentifier, parts[1], AlgName)
|
||||
}
|
||||
|
||||
return variant, parts[2:], nil
|
||||
}
|
||||
|
||||
func decode(variant Variant, parts []string) (digest algorithm.Digest, err error) {
|
||||
decoded := &Digest{
|
||||
variant: variant,
|
||||
}
|
||||
|
||||
var (
|
||||
ip, is, ik int
|
||||
)
|
||||
|
||||
switch len(parts) {
|
||||
case 2:
|
||||
ip, is, ik = -1, 0, 1
|
||||
case 3:
|
||||
ip, is, ik = 0, 1, 2
|
||||
}
|
||||
|
||||
if len(parts[ik]) == 0 {
|
||||
return nil, fmt.Errorf("%w: key has 0 bytes", algorithm.ErrEncodedHashKeyEncoding)
|
||||
}
|
||||
|
||||
decoded.iterations = IterationsDefaultOmitted
|
||||
|
||||
var params []encoding.Parameter
|
||||
|
||||
if ip >= 0 {
|
||||
if params, err = encoding.DecodeParameterStr(parts[ip]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, param := range params {
|
||||
switch param.Key {
|
||||
case "rounds":
|
||||
var rounds uint64
|
||||
|
||||
if rounds, err = strconv.ParseUint(param.Value, 10, 32); err != nil {
|
||||
return nil, fmt.Errorf("%w: option '%s' has invalid value '%s': %v", algorithm.ErrEncodedHashInvalidOptionValue, param.Key, param.Value, err)
|
||||
}
|
||||
|
||||
decoded.iterations = int(rounds)
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: option '%s' with value '%s' is unknown", algorithm.ErrEncodedHashInvalidOptionKey, param.Key, param.Value)
|
||||
}
|
||||
}
|
||||
|
||||
decoded.salt, decoded.key = []byte(parts[is]), []byte(parts[ik])
|
||||
|
||||
return decoded, nil
|
||||
}
|
||||
83
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/digest.go
generated
vendored
Normal file
83
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/digest.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package shacrypt
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
xcrypt "github.com/go-crypt/x/crypt"
|
||||
|
||||
"github.com/go-crypt/crypt/algorithm"
|
||||
)
|
||||
|
||||
// Digest is a digest which handles SHA-crypt hashes like SHA256 or SHA512.
|
||||
type Digest struct {
|
||||
variant Variant
|
||||
|
||||
iterations int
|
||||
salt, key []byte
|
||||
}
|
||||
|
||||
// Match returns true if the string password matches the current shacrypt.Digest.
|
||||
func (d *Digest) Match(password string) (match bool) {
|
||||
return d.MatchBytes([]byte(password))
|
||||
}
|
||||
|
||||
// MatchBytes returns true if the []byte passwordBytes matches the current shacrypt.Digest.
|
||||
func (d *Digest) MatchBytes(passwordBytes []byte) (match bool) {
|
||||
match, _ = d.MatchBytesAdvanced(passwordBytes)
|
||||
|
||||
return match
|
||||
}
|
||||
|
||||
// MatchAdvanced is the same as Match except if there is an error it returns that as well.
|
||||
func (d *Digest) MatchAdvanced(password string) (match bool, err error) {
|
||||
if match, err = d.MatchBytesAdvanced([]byte(password)); err != nil {
|
||||
return match, fmt.Errorf(algorithm.ErrFmtDigestMatch, AlgName, err)
|
||||
}
|
||||
|
||||
return match, nil
|
||||
}
|
||||
|
||||
// MatchBytesAdvanced is the same as MatchBytes except if there is an error it returns that as well.
|
||||
func (d *Digest) MatchBytesAdvanced(passwordBytes []byte) (match bool, err error) {
|
||||
if len(d.key) == 0 {
|
||||
return false, fmt.Errorf("%w: key has 0 bytes", algorithm.ErrPasswordInvalid)
|
||||
}
|
||||
|
||||
return subtle.ConstantTimeCompare(d.key, xcrypt.KeySHACrypt(d.variant.HashFunc(), passwordBytes, d.salt, d.iterations)) == 1, nil
|
||||
}
|
||||
|
||||
// Encode this Digest as a string for storage.
|
||||
func (d *Digest) Encode() (hash string) {
|
||||
switch d.iterations {
|
||||
case IterationsDefaultOmitted:
|
||||
return strings.ReplaceAll(fmt.Sprintf(EncodingFmtRoundsOmitted,
|
||||
d.variant.Prefix(),
|
||||
d.salt, d.key,
|
||||
), "\n", "")
|
||||
default:
|
||||
return strings.ReplaceAll(fmt.Sprintf(EncodingFmt,
|
||||
d.variant.Prefix(), d.iterations,
|
||||
d.salt, d.key,
|
||||
), "\n", "")
|
||||
}
|
||||
}
|
||||
|
||||
// String returns the storable format of the shacrypt.Digest hash utilizing fmt.Sprintf and shacrypt.EncodingFmt.
|
||||
func (d *Digest) String() string {
|
||||
return d.Encode()
|
||||
}
|
||||
|
||||
func (d *Digest) defaults() {
|
||||
switch d.variant {
|
||||
case VariantSHA256, VariantSHA512:
|
||||
break
|
||||
default:
|
||||
d.variant = variantDefault
|
||||
}
|
||||
|
||||
if d.iterations == 0 {
|
||||
d.iterations = d.variant.DefaultIterations()
|
||||
}
|
||||
}
|
||||
7
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/doc.go
generated
vendored
Normal file
7
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/doc.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// Package shacrypt provides helpful abstractions for an implementation of SHA-crypt and implements
|
||||
// github.com/go-crypt/crypt interfaces.
|
||||
//
|
||||
// See https://www.akkadia.org/drepper/SHA-crypt.html for specification details.
|
||||
//
|
||||
// This implementation is loaded by crypt.NewDefaultDecoder and crypt.NewDecoderAll.
|
||||
package shacrypt
|
||||
156
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/hasher.go
generated
vendored
Normal file
156
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/hasher.go
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
package shacrypt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
xcrypt "github.com/go-crypt/x/crypt"
|
||||
|
||||
"github.com/go-crypt/crypt/algorithm"
|
||||
"github.com/go-crypt/crypt/internal/random"
|
||||
)
|
||||
|
||||
// New returns a *Hasher without any settings configured. This d to a SHA512 hash.Hash
|
||||
// with 1000000 iterations. These settings can be overridden with the methods with the With prefix.
|
||||
func New(opts ...Opt) (hasher *Hasher, err error) {
|
||||
hasher = &Hasher{}
|
||||
|
||||
if err = hasher.WithOptions(opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = hasher.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hasher, nil
|
||||
}
|
||||
|
||||
// Hasher is a algorithm.Hash for SHA-crypt which can be initialized via shacrypt.New using a functional options pattern.
|
||||
type Hasher struct {
|
||||
variant Variant
|
||||
|
||||
iterations, bytesSalt int
|
||||
|
||||
d bool
|
||||
}
|
||||
|
||||
// NewSHA256 returns a *Hasher with the SHA256 hash.Hash which d to 1000000 iterations. These
|
||||
// settings can be overridden with the methods with the With prefix.
|
||||
func NewSHA256() (hasher *Hasher, err error) {
|
||||
return New(
|
||||
WithVariant(VariantSHA256),
|
||||
WithIterations(VariantSHA256.DefaultIterations()),
|
||||
)
|
||||
}
|
||||
|
||||
// NewSHA512 returns a *Hasher with the SHA512 hash.Hash which d to 1000000 iterations. These
|
||||
// settings can be overridden with the methods with the With prefix.
|
||||
func NewSHA512() (hasher *Hasher, err error) {
|
||||
return New(
|
||||
WithVariant(VariantSHA512),
|
||||
WithIterations(VariantSHA512.DefaultIterations()),
|
||||
)
|
||||
}
|
||||
|
||||
// WithOptions defines the options for this scrypt.Hasher.
|
||||
func (h *Hasher) WithOptions(opts ...Opt) (err error) {
|
||||
for _, opt := range opts {
|
||||
if err = opt(h); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hash performs the hashing operation and returns either a shacrypt.Digest as a algorithm.Digest or an error.
|
||||
func (h *Hasher) Hash(password string) (digest algorithm.Digest, err error) {
|
||||
h.defaults()
|
||||
|
||||
if digest, err = h.hash(password); err != nil {
|
||||
return nil, fmt.Errorf(algorithm.ErrFmtHasherHash, AlgName, err)
|
||||
}
|
||||
|
||||
return digest, nil
|
||||
}
|
||||
|
||||
func (h *Hasher) hash(password string) (digest algorithm.Digest, err error) {
|
||||
var salt []byte
|
||||
|
||||
if salt, err = random.CharSetBytes(h.bytesSalt, SaltCharSet); err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", algorithm.ErrSaltReadRandomBytes, err)
|
||||
}
|
||||
|
||||
return h.hashWithSalt(password, salt)
|
||||
}
|
||||
|
||||
// HashWithSalt overloads the Hash method allowing the user to provide a salt. It's recommended instead to configure the
|
||||
// salt size and let this be a random value generated using crypto/rand.
|
||||
func (h *Hasher) HashWithSalt(password string, salt []byte) (digest algorithm.Digest, err error) {
|
||||
h.defaults()
|
||||
|
||||
if digest, err = h.hashWithSalt(password, salt); err != nil {
|
||||
return nil, fmt.Errorf(algorithm.ErrFmtHasherHash, AlgName, err)
|
||||
}
|
||||
|
||||
return digest, nil
|
||||
}
|
||||
|
||||
func (h *Hasher) hashWithSalt(password string, salt []byte) (digest algorithm.Digest, err error) {
|
||||
if s := len(salt); s > SaltLengthMax || s < SaltLengthMin {
|
||||
return nil, fmt.Errorf("%w: salt bytes must have a length of between %d and %d but has a length of %d", algorithm.ErrSaltInvalid, SaltLengthMin, SaltLengthMax, len(salt))
|
||||
}
|
||||
|
||||
d := &Digest{
|
||||
variant: h.variant,
|
||||
iterations: h.iterations,
|
||||
salt: salt,
|
||||
}
|
||||
|
||||
d.defaults()
|
||||
|
||||
d.key = xcrypt.KeySHACrypt(d.variant.HashFunc(), []byte(password), d.salt, d.iterations)
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// MustHash overloads the Hash method and panics if the error is not nil. It's recommended if you use this option to
|
||||
// utilize the Validate method first or handle the panic appropriately.
|
||||
func (h *Hasher) MustHash(password string) (digest algorithm.Digest) {
|
||||
var err error
|
||||
|
||||
if digest, err = h.Hash(password); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return digest
|
||||
}
|
||||
|
||||
// Validate checks the settings/parameters for this shacrypt.Hasher and returns an error.
|
||||
func (h *Hasher) Validate() (err error) {
|
||||
h.defaults()
|
||||
|
||||
if err = h.validate(); err != nil {
|
||||
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Hasher) validate() (err error) {
|
||||
h.defaults()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Hasher) defaults() {
|
||||
if h.d {
|
||||
return
|
||||
}
|
||||
|
||||
h.d = true
|
||||
|
||||
if h.bytesSalt < SaltLengthMin {
|
||||
h.bytesSalt = algorithm.SaltLengthDefault
|
||||
}
|
||||
}
|
||||
98
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/opts.go
generated
vendored
Normal file
98
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/opts.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
package shacrypt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-crypt/crypt/algorithm"
|
||||
)
|
||||
|
||||
// Opt describes the functional option pattern for the shacrypt.Hasher.
|
||||
type Opt func(h *Hasher) (err error)
|
||||
|
||||
// WithVariant configures the shacrypt.Variant of the resulting shacrypt.Digest.
|
||||
// Default is shacrypt.VariantSHA512.
|
||||
func WithVariant(variant Variant) Opt {
|
||||
return func(h *Hasher) (err error) {
|
||||
switch variant {
|
||||
case VariantNone:
|
||||
return nil
|
||||
case VariantSHA256, VariantSHA512:
|
||||
h.variant = variant
|
||||
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf("%w: variant '%d' is invalid", algorithm.ErrParameterInvalid, variant))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithVariantName uses the variant name or identifier to configure the shacrypt.Variant of the resulting shacrypt.Digest.
|
||||
// Default is shacrypt.VariantSHA512.
|
||||
func WithVariantName(identifier string) Opt {
|
||||
return func(h *Hasher) (err error) {
|
||||
if identifier == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
variant := NewVariant(identifier)
|
||||
|
||||
if variant == VariantNone {
|
||||
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf("%w: variant identifier '%s' is invalid", algorithm.ErrParameterInvalid, identifier))
|
||||
}
|
||||
|
||||
h.variant = variant
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSHA256 adjusts this Hasher to utilize the SHA256 hash.Hash.
|
||||
func WithSHA256() Opt {
|
||||
return func(h *Hasher) (err error) {
|
||||
h.variant = VariantSHA256
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSHA512 adjusts this Hasher to utilize the SHA512 hash.Hash.
|
||||
func WithSHA512() Opt {
|
||||
return func(h *Hasher) (err error) {
|
||||
h.variant = VariantSHA512
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithIterations sets the iterations parameter of the resulting shacrypt.Digest.
|
||||
// Minimum 1000, Maximum 999999999. Default is 1000000.
|
||||
func WithIterations(iterations int) Opt {
|
||||
return func(h *Hasher) (err error) {
|
||||
if iterations < IterationsMin || iterations > IterationsMax {
|
||||
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf(algorithm.ErrFmtInvalidIntParameter, algorithm.ErrParameterInvalid, "iterations", IterationsMin, "", IterationsMax, iterations))
|
||||
}
|
||||
|
||||
h.iterations = iterations
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRounds is an alias for shacrypt.WithIterations.
|
||||
func WithRounds(rounds int) Opt {
|
||||
return WithIterations(rounds)
|
||||
}
|
||||
|
||||
// WithSaltLength adjusts the salt size (in bytes) of the resulting shacrypt.Digest.
|
||||
// Minimum 1, Maximum 16. Default is 16.
|
||||
func WithSaltLength(bytes int) Opt {
|
||||
return func(h *Hasher) (err error) {
|
||||
if bytes < SaltLengthMin || bytes > SaltLengthMax {
|
||||
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf(algorithm.ErrFmtInvalidIntParameter, algorithm.ErrParameterInvalid, "salt length", SaltLengthMin, "", SaltLengthMax, bytes))
|
||||
}
|
||||
|
||||
h.bytesSalt = bytes
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
92
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/variant.go
generated
vendored
Normal file
92
vendor/github.com/go-crypt/crypt/algorithm/shacrypt/variant.go
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
package shacrypt
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
|
||||
"github.com/go-crypt/crypt/algorithm"
|
||||
)
|
||||
|
||||
// NewVariant converts an identifier string to a shacrypt.Variant.
|
||||
func NewVariant(identifier string) Variant {
|
||||
switch identifier {
|
||||
case AlgIdentifierSHA256, algorithm.DigestSHA256:
|
||||
return VariantSHA256
|
||||
case AlgIdentifierSHA512, algorithm.DigestSHA512:
|
||||
return VariantSHA512
|
||||
default:
|
||||
return VariantSHA512
|
||||
}
|
||||
}
|
||||
|
||||
// Variant is a variant of the shacrypt.Digest.
|
||||
type Variant int
|
||||
|
||||
const (
|
||||
// VariantNone is a variant of the shacrypt.Digest which is unknown.
|
||||
VariantNone Variant = iota
|
||||
|
||||
// VariantSHA256 is a variant of the shacrypt.Digest which uses SHA-256.
|
||||
VariantSHA256
|
||||
|
||||
// VariantSHA512 is a variant of the shacrypt.Digest which uses SHA-512.
|
||||
VariantSHA512
|
||||
)
|
||||
|
||||
// String implements the fmt.Stringer returning a string representation of the shacrypt.Variant.
|
||||
func (v Variant) String() (identifier string) {
|
||||
switch v {
|
||||
case VariantSHA256:
|
||||
return algorithm.DigestSHA256
|
||||
case VariantSHA512:
|
||||
return algorithm.DigestSHA512
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Prefix returns the shacrypt.Variant prefix identifier.
|
||||
func (v Variant) Prefix() (prefix string) {
|
||||
switch v {
|
||||
case VariantSHA256:
|
||||
return AlgIdentifierSHA256
|
||||
case VariantSHA512:
|
||||
return AlgIdentifierSHA512
|
||||
default:
|
||||
return AlgIdentifierSHA512
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the Variant name.
|
||||
func (v Variant) Name() (s string) {
|
||||
switch v {
|
||||
case VariantSHA256:
|
||||
return algorithm.DigestSHA256
|
||||
case VariantSHA512:
|
||||
return algorithm.DigestSHA512
|
||||
default:
|
||||
return algorithm.DigestSHA512
|
||||
}
|
||||
}
|
||||
|
||||
// HashFunc returns the internal HMAC HashFunc.
|
||||
func (v Variant) HashFunc() algorithm.HashFunc {
|
||||
switch v {
|
||||
case VariantSHA256:
|
||||
return sha256.New
|
||||
case VariantSHA512:
|
||||
return sha512.New
|
||||
default:
|
||||
return sha512.New
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultIterations returns the default iterations for the particular variant.
|
||||
func (v Variant) DefaultIterations() int {
|
||||
switch v {
|
||||
case VariantSHA512:
|
||||
return IterationsDefaultSHA512
|
||||
default:
|
||||
return IterationsDefaultSHA256
|
||||
}
|
||||
}
|
||||
62
vendor/github.com/go-crypt/crypt/algorithm/types.go
generated
vendored
Normal file
62
vendor/github.com/go-crypt/crypt/algorithm/types.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package algorithm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash"
|
||||
)
|
||||
|
||||
// Hash is an interface which implements password hashing.
|
||||
type Hash interface {
|
||||
// Validate checks the hasher configuration to ensure it's valid. This should be used when the Hash is going to be
|
||||
// reused and you should use it in conjunction with MustHash.
|
||||
Validate() (err error)
|
||||
|
||||
// Hash performs the hashing operation on a password and resets any relevant parameters such as a manually set salt.
|
||||
// It then returns a Digest and error.
|
||||
Hash(password string) (hashed Digest, err error)
|
||||
|
||||
// HashWithSalt is an overload of Digest that also accepts a salt.
|
||||
HashWithSalt(password string, salt []byte) (hashed Digest, err error)
|
||||
|
||||
// MustHash overloads the Hash method and panics if the error is not nil. It's recommended if you use this method to
|
||||
// utilize the Validate method first or handle the panic appropriately.
|
||||
MustHash(password string) (hashed Digest)
|
||||
}
|
||||
|
||||
// Matcher is an interface used to match passwords.
|
||||
type Matcher interface {
|
||||
Match(password string) (match bool)
|
||||
MatchBytes(passwordBytes []byte) (match bool)
|
||||
MatchAdvanced(password string) (match bool, err error)
|
||||
MatchBytesAdvanced(passwordBytes []byte) (match bool, err error)
|
||||
}
|
||||
|
||||
// Digest represents a hashed password. It's implemented by all hashed password results so that when we pass a
|
||||
// stored hash into its relevant type we can verify the password against the hash.
|
||||
type Digest interface {
|
||||
fmt.Stringer
|
||||
|
||||
Matcher
|
||||
|
||||
Encode() (hash string)
|
||||
}
|
||||
|
||||
// DecodeFunc describes a function to decode an encoded digest into a algorithm.Digest.
|
||||
type DecodeFunc func(encodedDigest string) (digest Digest, err error)
|
||||
|
||||
// DecoderRegister describes an implementation that allows registering DecodeFunc's.
|
||||
type DecoderRegister interface {
|
||||
RegisterDecodeFunc(prefix string, decoder DecodeFunc) (err error)
|
||||
RegisterDecodePrefix(prefix, identifier string) (err error)
|
||||
|
||||
Decoder
|
||||
}
|
||||
|
||||
// Decoder is a representation of a implementation that performs generic decoding. Currently this is just intended for
|
||||
// use by implementers.
|
||||
type Decoder interface {
|
||||
Decode(encodedDigest string) (digest Digest, err error)
|
||||
}
|
||||
|
||||
// HashFunc is a function which returns a hash.Hash.
|
||||
type HashFunc func() hash.Hash
|
||||
Reference in New Issue
Block a user