mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-06 08:22:24 +01:00
fix (build): broken build on dependency
This commit is contained in:
parent
b1da883cff
commit
d554c81fa5
12 changed files with 1077 additions and 5 deletions
|
|
@ -6,11 +6,12 @@ import (
|
|||
"encoding/base64"
|
||||
"fmt"
|
||||
. "github.com/mickael-kerjean/filestash/server/common"
|
||||
"github.com/tredoe/osutil/user/crypt"
|
||||
"github.com/tredoe/osutil/user/crypt/apr1_crypt"
|
||||
"github.com/tredoe/osutil/user/crypt/md5_crypt"
|
||||
"github.com/tredoe/osutil/user/crypt/sha256_crypt"
|
||||
"github.com/tredoe/osutil/user/crypt/sha512_crypt"
|
||||
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt"
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/apr1_crypt"
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/md5_crypt"
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/sha256_crypt"
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/sha512_crypt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
|
|
|||
8
server/plugin/plg_authenticate_htpasswd/vendor/crypt/AUTHORS.md
vendored
Normal file
8
server/plugin/plg_authenticate_htpasswd/vendor/crypt/AUTHORS.md
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
### Initial author
|
||||
|
||||
[Jeramey Crawford](https://github.com/jeramey)
|
||||
|
||||
### Other authors
|
||||
|
||||
[Jonas mg](https://github.com/tredoe)
|
||||
|
||||
27
server/plugin/plg_authenticate_htpasswd/vendor/crypt/LICENSE
vendored
Normal file
27
server/plugin/plg_authenticate_htpasswd/vendor/crypt/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2012, Jeramey Crawford <jeramey@antihe.ro>
|
||||
Copyright (c) 2013, Jonas mg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
25
server/plugin/plg_authenticate_htpasswd/vendor/crypt/README.md
vendored
Normal file
25
server/plugin/plg_authenticate_htpasswd/vendor/crypt/README.md
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
crypt
|
||||
=====
|
||||
A password hashing library.
|
||||
|
||||
The goal of crypt is to bring a library of many common and popular password
|
||||
hashing algorithms to Go and to provide a simple and consistent interface to
|
||||
each of them. As every hashing method is implemented in pure Go, this library
|
||||
should be as portable as Go itself.
|
||||
|
||||
All hashing methods come with a test suite which verifies their operation
|
||||
against itself as well as the output of other password hashing implementations
|
||||
to ensure compatibility with them.
|
||||
|
||||
I hope you find this library to be useful and easy to use!
|
||||
|
||||
Note: forked from <https://github.com/jeramey/go-pwhash>
|
||||
|
||||
## Installation
|
||||
|
||||
go get github.com/tredoe/osutil/user/crypt
|
||||
|
||||
## License
|
||||
|
||||
The source files are distributed under a BSD-style license that can be found
|
||||
in the LICENSE file.
|
||||
62
server/plugin/plg_authenticate_htpasswd/vendor/crypt/apr1_crypt/apr1_crypt.go
vendored
Normal file
62
server/plugin/plg_authenticate_htpasswd/vendor/crypt/apr1_crypt/apr1_crypt.go
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>
|
||||
// Copyright 2013, Jonas mg
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package apr1_crypt implements the standard Unix MD5-crypt algorithm created
|
||||
// by Poul-Henning Kamp for FreeBSD, and modified by the Apache project.
|
||||
//
|
||||
// The only change from MD5-crypt is the use of the magic constant "$apr1$"
|
||||
// instead of "$1$". The algorithms are otherwise identical.
|
||||
package apr1_crypt
|
||||
|
||||
import (
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt"
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/common"
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/md5_crypt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
crypt.RegisterCrypt(crypt.APR1, New, MagicPrefix)
|
||||
}
|
||||
|
||||
const (
|
||||
MagicPrefix = "$apr1$"
|
||||
SaltLenMin = 1
|
||||
SaltLenMax = 8
|
||||
RoundsDefault = 1000
|
||||
)
|
||||
|
||||
var md5Crypt = md5_crypt.New()
|
||||
|
||||
func init() {
|
||||
md5Crypt.SetSalt(GetSalt())
|
||||
}
|
||||
|
||||
type crypter struct{ Salt common.Salt }
|
||||
|
||||
// New returns a new crypt.Crypter computing the variant "apr1" of MD5-crypt
|
||||
func New() crypt.Crypter { return &crypter{common.Salt{}} }
|
||||
|
||||
func (c *crypter) Generate(key, salt []byte) (string, error) {
|
||||
return md5Crypt.Generate(key, salt)
|
||||
}
|
||||
|
||||
func (c *crypter) Verify(hashedKey string, key []byte) error {
|
||||
return md5Crypt.Verify(hashedKey, key)
|
||||
}
|
||||
|
||||
func (c *crypter) Cost(hashedKey string) (int, error) { return RoundsDefault, nil }
|
||||
|
||||
func (c *crypter) SetSalt(salt common.Salt) {}
|
||||
|
||||
func GetSalt() common.Salt {
|
||||
return common.Salt{
|
||||
MagicPrefix: []byte(MagicPrefix),
|
||||
SaltLenMin: SaltLenMin,
|
||||
SaltLenMax: SaltLenMax,
|
||||
RoundsDefault: RoundsDefault,
|
||||
}
|
||||
}
|
||||
60
server/plugin/plg_authenticate_htpasswd/vendor/crypt/common/base64.go
vendored
Normal file
60
server/plugin/plg_authenticate_htpasswd/vendor/crypt/common/base64.go
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>
|
||||
// Copyright 2013, Jonas mg
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package common
|
||||
|
||||
const alphabet = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
// Base64_24Bit is a variant of Base64 encoding, commonly used with password
|
||||
// hashing algorithms to encode the result of their checksum output.
|
||||
//
|
||||
// The algorithm operates on up to 3 bytes at a time, encoding the following
|
||||
// 6-bit sequences into up to 4 hash64 ASCII bytes.
|
||||
//
|
||||
// 1. Bottom 6 bits of the first byte
|
||||
// 2. Top 2 bits of the first byte, and bottom 4 bits of the second byte.
|
||||
// 3. Top 4 bits of the second byte, and bottom 2 bits of the third byte.
|
||||
// 4. Top 6 bits of the third byte.
|
||||
//
|
||||
// This encoding method does not emit padding bytes as Base64 does.
|
||||
func Base64_24Bit(src []byte) (hash []byte) {
|
||||
if len(src) == 0 {
|
||||
return []byte{} // TODO: return nil
|
||||
}
|
||||
|
||||
hashSize := (len(src) * 8) / 6
|
||||
if (len(src) % 6) != 0 {
|
||||
hashSize += 1
|
||||
}
|
||||
hash = make([]byte, hashSize)
|
||||
|
||||
dst := hash
|
||||
for len(src) > 0 {
|
||||
switch len(src) {
|
||||
default:
|
||||
dst[0] = alphabet[src[0]&0x3f]
|
||||
dst[1] = alphabet[((src[0]>>6)|(src[1]<<2))&0x3f]
|
||||
dst[2] = alphabet[((src[1]>>4)|(src[2]<<4))&0x3f]
|
||||
dst[3] = alphabet[(src[2]>>2)&0x3f]
|
||||
src = src[3:]
|
||||
dst = dst[4:]
|
||||
case 2:
|
||||
dst[0] = alphabet[src[0]&0x3f]
|
||||
dst[1] = alphabet[((src[0]>>6)|(src[1]<<2))&0x3f]
|
||||
dst[2] = alphabet[(src[1]>>4)&0x3f]
|
||||
src = src[2:]
|
||||
dst = dst[3:]
|
||||
case 1:
|
||||
dst[0] = alphabet[src[0]&0x3f]
|
||||
dst[1] = alphabet[(src[0]>>6)&0x3f]
|
||||
src = src[1:]
|
||||
dst = dst[2:]
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
13
server/plugin/plg_authenticate_htpasswd/vendor/crypt/common/doc.go
vendored
Normal file
13
server/plugin/plg_authenticate_htpasswd/vendor/crypt/common/doc.go
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>
|
||||
// Copyright 2013, Jonas mg
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package common contains routines used by multiple password hashing
|
||||
// algorithms.
|
||||
//
|
||||
// Generally, you will never import this package directly. Many of the
|
||||
// *_crypt packages will import this package if they require it.
|
||||
package common
|
||||
105
server/plugin/plg_authenticate_htpasswd/vendor/crypt/common/salt.go
vendored
Normal file
105
server/plugin/plg_authenticate_htpasswd/vendor/crypt/common/salt.go
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>
|
||||
// Copyright 2013, Jonas mg
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrSaltPrefix = errors.New("invalid magic prefix")
|
||||
ErrSaltFormat = errors.New("invalid salt format")
|
||||
ErrSaltRounds = errors.New("invalid rounds")
|
||||
)
|
||||
|
||||
// Salt represents a salt.
|
||||
type Salt struct {
|
||||
MagicPrefix []byte
|
||||
|
||||
SaltLenMin int
|
||||
SaltLenMax int
|
||||
|
||||
RoundsMin int
|
||||
RoundsMax int
|
||||
RoundsDefault int
|
||||
}
|
||||
|
||||
// Generate generates a random salt of a given length.
|
||||
//
|
||||
// The length is set thus:
|
||||
//
|
||||
// length > SaltLenMax: length = SaltLenMax
|
||||
// length < SaltLenMin: length = SaltLenMin
|
||||
func (s *Salt) Generate(length int) []byte {
|
||||
if length > s.SaltLenMax {
|
||||
length = s.SaltLenMax
|
||||
} else if length < s.SaltLenMin {
|
||||
length = s.SaltLenMin
|
||||
}
|
||||
|
||||
saltLen := (length * 6 / 8)
|
||||
if (length*6)%8 != 0 {
|
||||
saltLen++
|
||||
}
|
||||
salt := make([]byte, saltLen)
|
||||
rand.Read(salt)
|
||||
|
||||
out := make([]byte, len(s.MagicPrefix)+length)
|
||||
copy(out, s.MagicPrefix)
|
||||
copy(out[len(s.MagicPrefix):], Base64_24Bit(salt))
|
||||
return out
|
||||
}
|
||||
|
||||
// GenerateWRounds creates a random salt with the random bytes being of the
|
||||
// length provided, and the rounds parameter set as specified.
|
||||
//
|
||||
// The parameters are set thus:
|
||||
//
|
||||
// length > SaltLenMax: length = SaltLenMax
|
||||
// length < SaltLenMin: length = SaltLenMin
|
||||
//
|
||||
// rounds < 0: rounds = RoundsDefault
|
||||
// rounds < RoundsMin: rounds = RoundsMin
|
||||
// rounds > RoundsMax: rounds = RoundsMax
|
||||
//
|
||||
// If rounds is equal to RoundsDefault, then the "rounds=" part of the salt is
|
||||
// removed.
|
||||
func (s *Salt) GenerateWRounds(length, rounds int) []byte {
|
||||
if length > s.SaltLenMax {
|
||||
length = s.SaltLenMax
|
||||
} else if length < s.SaltLenMin {
|
||||
length = s.SaltLenMin
|
||||
}
|
||||
if rounds < 0 {
|
||||
rounds = s.RoundsDefault
|
||||
} else if rounds < s.RoundsMin {
|
||||
rounds = s.RoundsMin
|
||||
} else if rounds > s.RoundsMax {
|
||||
rounds = s.RoundsMax
|
||||
}
|
||||
|
||||
saltLen := (length * 6 / 8)
|
||||
if (length*6)%8 != 0 {
|
||||
saltLen++
|
||||
}
|
||||
salt := make([]byte, saltLen)
|
||||
rand.Read(salt)
|
||||
|
||||
roundsText := ""
|
||||
if rounds != s.RoundsDefault {
|
||||
roundsText = "rounds=" + strconv.Itoa(rounds) + "$"
|
||||
}
|
||||
|
||||
out := make([]byte, len(s.MagicPrefix)+len(roundsText)+length)
|
||||
copy(out, s.MagicPrefix)
|
||||
copy(out[len(s.MagicPrefix):], []byte(roundsText))
|
||||
copy(out[len(s.MagicPrefix)+len(roundsText):], Base64_24Bit(salt))
|
||||
return out
|
||||
}
|
||||
108
server/plugin/plg_authenticate_htpasswd/vendor/crypt/crypt.go
vendored
Normal file
108
server/plugin/plg_authenticate_htpasswd/vendor/crypt/crypt.go
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright 2013, Jonas mg
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package crypt provides interface for password crypt functions and collects
|
||||
// common constants.
|
||||
package crypt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/common"
|
||||
)
|
||||
|
||||
var ErrKeyMismatch = errors.New("hashed value is not the hash of the given password")
|
||||
|
||||
// Crypter is the common interface implemented by all crypt functions.
|
||||
type Crypter interface {
|
||||
// Generate performs the hashing algorithm, returning a full hash suitable
|
||||
// for storage and later password verification.
|
||||
//
|
||||
// If the salt is empty, a randomly-generated salt will be generated with a
|
||||
// length of SaltLenMax and number RoundsDefault of rounds.
|
||||
//
|
||||
// Any error only can be got when the salt argument is not empty.
|
||||
Generate(key, salt []byte) (string, error)
|
||||
|
||||
// Verify compares a hashed key with its possible key equivalent.
|
||||
// Returns nil on success, or an error on failure; if the hashed key is
|
||||
// diffrent, the error is "ErrKeyMismatch".
|
||||
Verify(hashedKey string, key []byte) error
|
||||
|
||||
// Cost returns the hashing cost (in rounds) used to create the given hashed
|
||||
// key.
|
||||
//
|
||||
// When, in the future, the hashing cost of a key needs to be increased in
|
||||
// order to adjust for greater computational power, this function allows one
|
||||
// to establish which keys need to be updated.
|
||||
//
|
||||
// The algorithms based in MD5-crypt use a fixed value of rounds.
|
||||
Cost(hashedKey string) (int, error)
|
||||
|
||||
// SetSalt sets a different salt. It is used to easily create derivated
|
||||
// algorithms, i.e. "apr1_crypt" from "md5_crypt".
|
||||
SetSalt(salt common.Salt)
|
||||
}
|
||||
|
||||
// Crypt identifies a crypt function that is implemented in another package.
|
||||
type Crypt uint
|
||||
|
||||
const (
|
||||
APR1 Crypt = iota + 1 // import "github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/apr1_crypt"
|
||||
MD5 // import "github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/md5_crypt"
|
||||
SHA256 // import "github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/sha256_crypt"
|
||||
SHA512 // import "github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/sha512_crypt"
|
||||
maxCrypt
|
||||
)
|
||||
|
||||
var cryptPrefixes = make([]string, maxCrypt)
|
||||
|
||||
var crypts = make([]func() Crypter, maxCrypt)
|
||||
|
||||
// RegisterCrypt registers a function that returns a new instance of the given
|
||||
// crypt function. This is intended to be called from the init function in
|
||||
// packages that implement crypt functions.
|
||||
func RegisterCrypt(c Crypt, f func() Crypter, prefix string) {
|
||||
if c >= maxCrypt {
|
||||
panic("crypt: RegisterHash of unknown crypt function")
|
||||
}
|
||||
crypts[c] = f
|
||||
cryptPrefixes[c] = prefix
|
||||
}
|
||||
|
||||
// New returns a new crypter.
|
||||
func New(c Crypt) Crypter {
|
||||
f := crypts[c]
|
||||
if f != nil {
|
||||
return f()
|
||||
}
|
||||
panic("crypt: requested crypt function is unavailable")
|
||||
}
|
||||
|
||||
// NewFromHash returns a new Crypter using the prefix in the given hashed key.
|
||||
func NewFromHash(hashedKey string) Crypter {
|
||||
var f func() Crypter
|
||||
|
||||
if strings.HasPrefix(hashedKey, cryptPrefixes[SHA512]) {
|
||||
f = crypts[SHA512]
|
||||
} else if strings.HasPrefix(hashedKey, cryptPrefixes[SHA256]) {
|
||||
f = crypts[SHA256]
|
||||
} else if strings.HasPrefix(hashedKey, cryptPrefixes[MD5]) {
|
||||
f = crypts[MD5]
|
||||
} else if strings.HasPrefix(hashedKey, cryptPrefixes[APR1]) {
|
||||
f = crypts[APR1]
|
||||
} else {
|
||||
toks := strings.SplitN(hashedKey, "$", 3)
|
||||
prefix := "$" + toks[1] + "$"
|
||||
panic("crypt: unknown cryp function from prefix: " + prefix)
|
||||
}
|
||||
|
||||
if f != nil {
|
||||
return f()
|
||||
}
|
||||
panic("crypt: requested cryp function is unavailable")
|
||||
}
|
||||
166
server/plugin/plg_authenticate_htpasswd/vendor/crypt/md5_crypt/md5_crypt.go
vendored
Normal file
166
server/plugin/plg_authenticate_htpasswd/vendor/crypt/md5_crypt/md5_crypt.go
vendored
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
// Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>
|
||||
// Copyright 2013, Jonas mg
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package md5_crypt implements the standard Unix MD5-crypt algorithm created by
|
||||
// Poul-Henning Kamp for FreeBSD.
|
||||
package md5_crypt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt"
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/common"
|
||||
)
|
||||
|
||||
func init() {
|
||||
crypt.RegisterCrypt(crypt.MD5, New, MagicPrefix)
|
||||
}
|
||||
|
||||
// NOTE: Cisco IOS only allows salts of length 4.
|
||||
|
||||
const (
|
||||
MagicPrefix = "$1$"
|
||||
SaltLenMin = 1 // Real minimum is 0, but that isn't useful.
|
||||
SaltLenMax = 8
|
||||
RoundsDefault = 1000
|
||||
)
|
||||
|
||||
type crypter struct{ Salt common.Salt }
|
||||
|
||||
// New returns a new crypt.Crypter computing the MD5-crypt password hashing.
|
||||
func New() crypt.Crypter {
|
||||
return &crypter{GetSalt()}
|
||||
}
|
||||
|
||||
func (c *crypter) Generate(key, salt []byte) (string, error) {
|
||||
if len(salt) == 0 {
|
||||
salt = c.Salt.Generate(SaltLenMax)
|
||||
}
|
||||
if !bytes.HasPrefix(salt, c.Salt.MagicPrefix) {
|
||||
return "", common.ErrSaltPrefix
|
||||
}
|
||||
|
||||
saltToks := bytes.Split(salt, []byte{'$'})
|
||||
|
||||
if len(saltToks) < 3 {
|
||||
return "", common.ErrSaltFormat
|
||||
} else {
|
||||
salt = saltToks[2]
|
||||
}
|
||||
if len(salt) > 8 {
|
||||
salt = salt[0:8]
|
||||
}
|
||||
|
||||
// Compute alternate MD5 sum with input KEY, SALT, and KEY.
|
||||
Alternate := md5.New()
|
||||
Alternate.Write(key)
|
||||
Alternate.Write(salt)
|
||||
Alternate.Write(key)
|
||||
AlternateSum := Alternate.Sum(nil) // 16 bytes
|
||||
|
||||
A := md5.New()
|
||||
A.Write(key)
|
||||
A.Write(c.Salt.MagicPrefix)
|
||||
A.Write(salt)
|
||||
// Add for any character in the key one byte of the alternate sum.
|
||||
i := len(key)
|
||||
for ; i > 16; i -= 16 {
|
||||
A.Write(AlternateSum)
|
||||
}
|
||||
A.Write(AlternateSum[0:i])
|
||||
|
||||
// The original implementation now does something weird:
|
||||
// For every 1 bit in the key, the first 0 is added to the buffer
|
||||
// For every 0 bit, the first character of the key
|
||||
// This does not seem to be what was intended but we have to follow this to
|
||||
// be compatible.
|
||||
for i = len(key); i > 0; i >>= 1 {
|
||||
if (i & 1) == 0 {
|
||||
A.Write(key[0:1])
|
||||
} else {
|
||||
A.Write([]byte{0})
|
||||
}
|
||||
}
|
||||
Csum := A.Sum(nil)
|
||||
|
||||
// In fear of password crackers here comes a quite long loop which just
|
||||
// processes the output of the previous round again.
|
||||
// We cannot ignore this here.
|
||||
for i = 0; i < RoundsDefault; i++ {
|
||||
C := md5.New()
|
||||
|
||||
// Add key or last result.
|
||||
if (i & 1) != 0 {
|
||||
C.Write(key)
|
||||
} else {
|
||||
C.Write(Csum)
|
||||
}
|
||||
// Add salt for numbers not divisible by 3.
|
||||
if (i % 3) != 0 {
|
||||
C.Write(salt)
|
||||
}
|
||||
// Add key for numbers not divisible by 7.
|
||||
if (i % 7) != 0 {
|
||||
C.Write(key)
|
||||
}
|
||||
// Add key or last result.
|
||||
if (i & 1) == 0 {
|
||||
C.Write(key)
|
||||
} else {
|
||||
C.Write(Csum)
|
||||
}
|
||||
|
||||
Csum = C.Sum(nil)
|
||||
}
|
||||
|
||||
out := make([]byte, 0, 23+len(c.Salt.MagicPrefix)+len(salt))
|
||||
out = append(out, c.Salt.MagicPrefix...)
|
||||
out = append(out, salt...)
|
||||
out = append(out, '$')
|
||||
out = append(out, common.Base64_24Bit([]byte{
|
||||
Csum[12], Csum[6], Csum[0],
|
||||
Csum[13], Csum[7], Csum[1],
|
||||
Csum[14], Csum[8], Csum[2],
|
||||
Csum[15], Csum[9], Csum[3],
|
||||
Csum[5], Csum[10], Csum[4],
|
||||
Csum[11],
|
||||
})...)
|
||||
|
||||
// Clean sensitive data.
|
||||
A.Reset()
|
||||
Alternate.Reset()
|
||||
for i = 0; i < len(AlternateSum); i++ {
|
||||
AlternateSum[i] = 0
|
||||
}
|
||||
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
func (c *crypter) Verify(hashedKey string, key []byte) error {
|
||||
newHash, err := c.Generate(key, []byte(hashedKey))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if newHash != hashedKey {
|
||||
return crypt.ErrKeyMismatch
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *crypter) Cost(hashedKey string) (int, error) { return RoundsDefault, nil }
|
||||
|
||||
func (c *crypter) SetSalt(salt common.Salt) { c.Salt = salt }
|
||||
|
||||
func GetSalt() common.Salt {
|
||||
return common.Salt{
|
||||
MagicPrefix: []byte(MagicPrefix),
|
||||
SaltLenMin: SaltLenMin,
|
||||
SaltLenMax: SaltLenMax,
|
||||
RoundsDefault: RoundsDefault,
|
||||
}
|
||||
}
|
||||
243
server/plugin/plg_authenticate_htpasswd/vendor/crypt/sha256_crypt/sha256_crypt.go
vendored
Normal file
243
server/plugin/plg_authenticate_htpasswd/vendor/crypt/sha256_crypt/sha256_crypt.go
vendored
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
// Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>
|
||||
// Copyright 2013, Jonas mg
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package sha256_crypt implements Ulrich Drepper's SHA256-crypt password
|
||||
// hashing algorithm.
|
||||
//
|
||||
// The specification for this algorithm can be found here:
|
||||
// http://www.akkadia.org/drepper/SHA-crypt.txt
|
||||
package sha256_crypt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"strconv"
|
||||
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt"
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/common"
|
||||
)
|
||||
|
||||
func init() {
|
||||
crypt.RegisterCrypt(crypt.SHA256, New, MagicPrefix)
|
||||
}
|
||||
|
||||
const (
|
||||
MagicPrefix = "$5$"
|
||||
SaltLenMin = 1
|
||||
SaltLenMax = 16
|
||||
RoundsMin = 1000
|
||||
RoundsMax = 999999999
|
||||
RoundsDefault = 5000
|
||||
)
|
||||
|
||||
var _rounds = []byte("rounds=")
|
||||
|
||||
type crypter struct{ Salt common.Salt }
|
||||
|
||||
// New returns a new crypt.Crypter computing the SHA256-crypt password hashing.
|
||||
func New() crypt.Crypter {
|
||||
return &crypter{GetSalt()}
|
||||
}
|
||||
|
||||
func (c *crypter) Generate(key, salt []byte) (string, error) {
|
||||
var rounds int
|
||||
var isRoundsDef bool
|
||||
|
||||
if len(salt) == 0 {
|
||||
salt = c.Salt.GenerateWRounds(SaltLenMax, RoundsDefault)
|
||||
}
|
||||
if !bytes.HasPrefix(salt, c.Salt.MagicPrefix) {
|
||||
return "", common.ErrSaltPrefix
|
||||
}
|
||||
|
||||
saltToks := bytes.Split(salt, []byte{'$'})
|
||||
if len(saltToks) < 3 {
|
||||
return "", common.ErrSaltFormat
|
||||
}
|
||||
|
||||
if bytes.HasPrefix(saltToks[2], _rounds) {
|
||||
isRoundsDef = true
|
||||
pr, err := strconv.ParseInt(string(saltToks[2][7:]), 10, 32)
|
||||
if err != nil {
|
||||
return "", common.ErrSaltRounds
|
||||
}
|
||||
rounds = int(pr)
|
||||
if rounds < RoundsMin {
|
||||
rounds = RoundsMin
|
||||
} else if rounds > RoundsMax {
|
||||
rounds = RoundsMax
|
||||
}
|
||||
salt = saltToks[3]
|
||||
} else {
|
||||
rounds = RoundsDefault
|
||||
salt = saltToks[2]
|
||||
}
|
||||
|
||||
if len(salt) > 16 {
|
||||
salt = salt[0:16]
|
||||
}
|
||||
|
||||
// Compute alternate SHA256 sum with input KEY, SALT, and KEY.
|
||||
Alternate := sha256.New()
|
||||
Alternate.Write(key)
|
||||
Alternate.Write(salt)
|
||||
Alternate.Write(key)
|
||||
AlternateSum := Alternate.Sum(nil) // 32 bytes
|
||||
|
||||
A := sha256.New()
|
||||
A.Write(key)
|
||||
A.Write(salt)
|
||||
// Add for any character in the key one byte of the alternate sum.
|
||||
i := len(key)
|
||||
for ; i > 32; i -= 32 {
|
||||
A.Write(AlternateSum)
|
||||
}
|
||||
A.Write(AlternateSum[0:i])
|
||||
|
||||
// Take the binary representation of the length of the key and for every add
|
||||
// the alternate sum, for every 0 the key.
|
||||
for i = len(key); i > 0; i >>= 1 {
|
||||
if (i & 1) != 0 {
|
||||
A.Write(AlternateSum)
|
||||
} else {
|
||||
A.Write(key)
|
||||
}
|
||||
}
|
||||
Asum := A.Sum(nil)
|
||||
|
||||
// Start computation of P byte sequence.
|
||||
P := sha256.New()
|
||||
// For every character in the password add the entire password.
|
||||
for i = 0; i < len(key); i++ {
|
||||
P.Write(key)
|
||||
}
|
||||
Psum := P.Sum(nil)
|
||||
// Create byte sequence P.
|
||||
Pseq := make([]byte, 0, len(key))
|
||||
for i = len(key); i > 32; i -= 32 {
|
||||
Pseq = append(Pseq, Psum...)
|
||||
}
|
||||
Pseq = append(Pseq, Psum[0:i]...)
|
||||
|
||||
// Start computation of S byte sequence.
|
||||
S := sha256.New()
|
||||
for i = 0; i < (16 + int(Asum[0])); i++ {
|
||||
S.Write(salt)
|
||||
}
|
||||
Ssum := S.Sum(nil)
|
||||
// Create byte sequence S.
|
||||
Sseq := make([]byte, 0, len(salt))
|
||||
for i = len(salt); i > 32; i -= 32 {
|
||||
Sseq = append(Sseq, Ssum...)
|
||||
}
|
||||
Sseq = append(Sseq, Ssum[0:i]...)
|
||||
|
||||
Csum := Asum
|
||||
|
||||
// Repeatedly run the collected hash value through SHA256 to burn CPU cycles.
|
||||
for i = 0; i < rounds; i++ {
|
||||
C := sha256.New()
|
||||
|
||||
// Add key or last result.
|
||||
if (i & 1) != 0 {
|
||||
C.Write(Pseq)
|
||||
} else {
|
||||
C.Write(Csum)
|
||||
}
|
||||
// Add salt for numbers not divisible by 3.
|
||||
if (i % 3) != 0 {
|
||||
C.Write(Sseq)
|
||||
}
|
||||
// Add key for numbers not divisible by 7.
|
||||
if (i % 7) != 0 {
|
||||
C.Write(Pseq)
|
||||
}
|
||||
// Add key or last result.
|
||||
if (i & 1) != 0 {
|
||||
C.Write(Csum)
|
||||
} else {
|
||||
C.Write(Pseq)
|
||||
}
|
||||
|
||||
Csum = C.Sum(nil)
|
||||
}
|
||||
|
||||
out := make([]byte, 0, 80)
|
||||
out = append(out, c.Salt.MagicPrefix...)
|
||||
if isRoundsDef {
|
||||
out = append(out, []byte("rounds="+strconv.Itoa(rounds)+"$")...)
|
||||
}
|
||||
out = append(out, salt...)
|
||||
out = append(out, '$')
|
||||
out = append(out, common.Base64_24Bit([]byte{
|
||||
Csum[20], Csum[10], Csum[0],
|
||||
Csum[11], Csum[1], Csum[21],
|
||||
Csum[2], Csum[22], Csum[12],
|
||||
Csum[23], Csum[13], Csum[3],
|
||||
Csum[14], Csum[4], Csum[24],
|
||||
Csum[5], Csum[25], Csum[15],
|
||||
Csum[26], Csum[16], Csum[6],
|
||||
Csum[17], Csum[7], Csum[27],
|
||||
Csum[8], Csum[28], Csum[18],
|
||||
Csum[29], Csum[19], Csum[9],
|
||||
Csum[30], Csum[31],
|
||||
})...)
|
||||
|
||||
// Clean sensitive data.
|
||||
A.Reset()
|
||||
Alternate.Reset()
|
||||
P.Reset()
|
||||
for i = 0; i < len(Asum); i++ {
|
||||
Asum[i] = 0
|
||||
}
|
||||
for i = 0; i < len(AlternateSum); i++ {
|
||||
AlternateSum[i] = 0
|
||||
}
|
||||
for i = 0; i < len(Pseq); i++ {
|
||||
Pseq[i] = 0
|
||||
}
|
||||
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
func (c *crypter) Verify(hashedKey string, key []byte) error {
|
||||
newHash, err := c.Generate(key, []byte(hashedKey))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if newHash != hashedKey {
|
||||
return crypt.ErrKeyMismatch
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *crypter) Cost(hashedKey string) (int, error) {
|
||||
saltToks := bytes.Split([]byte(hashedKey), []byte{'$'})
|
||||
if len(saltToks) < 3 {
|
||||
return 0, common.ErrSaltFormat
|
||||
}
|
||||
|
||||
if !bytes.HasPrefix(saltToks[2], _rounds) {
|
||||
return RoundsDefault, nil
|
||||
}
|
||||
roundToks := bytes.Split(saltToks[2], []byte{'='})
|
||||
cost, err := strconv.ParseInt(string(roundToks[1]), 10, 0)
|
||||
return int(cost), err
|
||||
}
|
||||
|
||||
func (c *crypter) SetSalt(salt common.Salt) { c.Salt = salt }
|
||||
|
||||
func GetSalt() common.Salt {
|
||||
return common.Salt{
|
||||
MagicPrefix: []byte(MagicPrefix),
|
||||
SaltLenMin: SaltLenMin,
|
||||
SaltLenMax: SaltLenMax,
|
||||
RoundsDefault: RoundsDefault,
|
||||
RoundsMin: RoundsMin,
|
||||
RoundsMax: RoundsMax,
|
||||
}
|
||||
}
|
||||
254
server/plugin/plg_authenticate_htpasswd/vendor/crypt/sha512_crypt/sha512_crypt.go
vendored
Normal file
254
server/plugin/plg_authenticate_htpasswd/vendor/crypt/sha512_crypt/sha512_crypt.go
vendored
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
// Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>
|
||||
// Copyright 2013, Jonas mg
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package sha512_crypt implements Ulrich Drepper's SHA512-crypt password
|
||||
// hashing algorithm.
|
||||
//
|
||||
// The specification for this algorithm can be found here:
|
||||
// http://www.akkadia.org/drepper/SHA-crypt.txt
|
||||
package sha512_crypt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha512"
|
||||
"strconv"
|
||||
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt"
|
||||
"github.com/mickael-kerjean/server/plg_authenticate_htpasswd/vendor/crypt/common"
|
||||
)
|
||||
|
||||
func init() {
|
||||
crypt.RegisterCrypt(crypt.SHA512, New, MagicPrefix)
|
||||
}
|
||||
|
||||
const (
|
||||
MagicPrefix = "$6$"
|
||||
SaltLenMin = 1
|
||||
SaltLenMax = 16
|
||||
RoundsMin = 1000
|
||||
RoundsMax = 999999999
|
||||
RoundsDefault = 5000
|
||||
)
|
||||
|
||||
var _rounds = []byte("rounds=")
|
||||
|
||||
type crypter struct{ Salt common.Salt }
|
||||
|
||||
// New returns a new crypt.Crypter computing the SHA512-crypt password hashing.
|
||||
func New() crypt.Crypter {
|
||||
return &crypter{GetSalt()}
|
||||
}
|
||||
|
||||
func (c *crypter) Generate(key, salt []byte) (string, error) {
|
||||
var rounds int
|
||||
var isRoundsDef bool
|
||||
|
||||
if len(salt) == 0 {
|
||||
salt = c.Salt.GenerateWRounds(SaltLenMax, RoundsDefault)
|
||||
}
|
||||
if !bytes.HasPrefix(salt, c.Salt.MagicPrefix) {
|
||||
return "", common.ErrSaltPrefix
|
||||
}
|
||||
|
||||
saltToks := bytes.Split(salt, []byte{'$'})
|
||||
if len(saltToks) < 3 {
|
||||
return "", common.ErrSaltFormat
|
||||
}
|
||||
|
||||
if bytes.HasPrefix(saltToks[2], _rounds) {
|
||||
isRoundsDef = true
|
||||
pr, err := strconv.ParseInt(string(saltToks[2][7:]), 10, 32)
|
||||
if err != nil {
|
||||
return "", common.ErrSaltRounds
|
||||
}
|
||||
rounds = int(pr)
|
||||
if rounds < RoundsMin {
|
||||
rounds = RoundsMin
|
||||
} else if rounds > RoundsMax {
|
||||
rounds = RoundsMax
|
||||
}
|
||||
salt = saltToks[3]
|
||||
} else {
|
||||
rounds = RoundsDefault
|
||||
salt = saltToks[2]
|
||||
}
|
||||
|
||||
if len(salt) > SaltLenMax {
|
||||
salt = salt[0:SaltLenMax]
|
||||
}
|
||||
|
||||
// Compute alternate SHA512 sum with input KEY, SALT, and KEY.
|
||||
Alternate := sha512.New()
|
||||
Alternate.Write(key)
|
||||
Alternate.Write(salt)
|
||||
Alternate.Write(key)
|
||||
AlternateSum := Alternate.Sum(nil) // 64 bytes
|
||||
|
||||
A := sha512.New()
|
||||
A.Write(key)
|
||||
A.Write(salt)
|
||||
// Add for any character in the key one byte of the alternate sum.
|
||||
i := len(key)
|
||||
for ; i > 64; i -= 64 {
|
||||
A.Write(AlternateSum)
|
||||
}
|
||||
A.Write(AlternateSum[0:i])
|
||||
|
||||
// Take the binary representation of the length of the key and for every add
|
||||
// the alternate sum, for every 0 the key.
|
||||
for i = len(key); i > 0; i >>= 1 {
|
||||
if (i & 1) != 0 {
|
||||
A.Write(AlternateSum)
|
||||
} else {
|
||||
A.Write(key)
|
||||
}
|
||||
}
|
||||
Asum := A.Sum(nil)
|
||||
|
||||
// Start computation of P byte sequence.
|
||||
P := sha512.New()
|
||||
// For every character in the password add the entire password.
|
||||
for i = 0; i < len(key); i++ {
|
||||
P.Write(key)
|
||||
}
|
||||
Psum := P.Sum(nil)
|
||||
// Create byte sequence P.
|
||||
Pseq := make([]byte, 0, len(key))
|
||||
for i = len(key); i > 64; i -= 64 {
|
||||
Pseq = append(Pseq, Psum...)
|
||||
}
|
||||
Pseq = append(Pseq, Psum[0:i]...)
|
||||
|
||||
// Start computation of S byte sequence.
|
||||
S := sha512.New()
|
||||
for i = 0; i < (16 + int(Asum[0])); i++ {
|
||||
S.Write(salt)
|
||||
}
|
||||
Ssum := S.Sum(nil)
|
||||
// Create byte sequence S.
|
||||
Sseq := make([]byte, 0, len(salt))
|
||||
for i = len(salt); i > 64; i -= 64 {
|
||||
Sseq = append(Sseq, Ssum...)
|
||||
}
|
||||
Sseq = append(Sseq, Ssum[0:i]...)
|
||||
|
||||
Csum := Asum
|
||||
|
||||
// Repeatedly run the collected hash value through SHA512 to burn CPU cycles.
|
||||
for i = 0; i < rounds; i++ {
|
||||
C := sha512.New()
|
||||
|
||||
// Add key or last result.
|
||||
if (i & 1) != 0 {
|
||||
C.Write(Pseq)
|
||||
} else {
|
||||
C.Write(Csum)
|
||||
}
|
||||
// Add salt for numbers not divisible by 3.
|
||||
if (i % 3) != 0 {
|
||||
C.Write(Sseq)
|
||||
}
|
||||
// Add key for numbers not divisible by 7.
|
||||
if (i % 7) != 0 {
|
||||
C.Write(Pseq)
|
||||
}
|
||||
// Add key or last result.
|
||||
if (i & 1) != 0 {
|
||||
C.Write(Csum)
|
||||
} else {
|
||||
C.Write(Pseq)
|
||||
}
|
||||
|
||||
Csum = C.Sum(nil)
|
||||
}
|
||||
|
||||
out := make([]byte, 0, 123)
|
||||
out = append(out, c.Salt.MagicPrefix...)
|
||||
if isRoundsDef {
|
||||
out = append(out, []byte("rounds="+strconv.Itoa(rounds)+"$")...)
|
||||
}
|
||||
out = append(out, salt...)
|
||||
out = append(out, '$')
|
||||
out = append(out, common.Base64_24Bit([]byte{
|
||||
Csum[42], Csum[21], Csum[0],
|
||||
Csum[1], Csum[43], Csum[22],
|
||||
Csum[23], Csum[2], Csum[44],
|
||||
Csum[45], Csum[24], Csum[3],
|
||||
Csum[4], Csum[46], Csum[25],
|
||||
Csum[26], Csum[5], Csum[47],
|
||||
Csum[48], Csum[27], Csum[6],
|
||||
Csum[7], Csum[49], Csum[28],
|
||||
Csum[29], Csum[8], Csum[50],
|
||||
Csum[51], Csum[30], Csum[9],
|
||||
Csum[10], Csum[52], Csum[31],
|
||||
Csum[32], Csum[11], Csum[53],
|
||||
Csum[54], Csum[33], Csum[12],
|
||||
Csum[13], Csum[55], Csum[34],
|
||||
Csum[35], Csum[14], Csum[56],
|
||||
Csum[57], Csum[36], Csum[15],
|
||||
Csum[16], Csum[58], Csum[37],
|
||||
Csum[38], Csum[17], Csum[59],
|
||||
Csum[60], Csum[39], Csum[18],
|
||||
Csum[19], Csum[61], Csum[40],
|
||||
Csum[41], Csum[20], Csum[62],
|
||||
Csum[63],
|
||||
})...)
|
||||
|
||||
// Clean sensitive data.
|
||||
A.Reset()
|
||||
Alternate.Reset()
|
||||
P.Reset()
|
||||
for i = 0; i < len(Asum); i++ {
|
||||
Asum[i] = 0
|
||||
}
|
||||
for i = 0; i < len(AlternateSum); i++ {
|
||||
AlternateSum[i] = 0
|
||||
}
|
||||
for i = 0; i < len(Pseq); i++ {
|
||||
Pseq[i] = 0
|
||||
}
|
||||
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
func (c *crypter) Verify(hashedKey string, key []byte) error {
|
||||
newHash, err := c.Generate(key, []byte(hashedKey))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if newHash != hashedKey {
|
||||
return crypt.ErrKeyMismatch
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *crypter) Cost(hashedKey string) (int, error) {
|
||||
saltToks := bytes.Split([]byte(hashedKey), []byte{'$'})
|
||||
if len(saltToks) < 3 {
|
||||
return 0, common.ErrSaltFormat
|
||||
}
|
||||
|
||||
if !bytes.HasPrefix(saltToks[2], _rounds) {
|
||||
return RoundsDefault, nil
|
||||
}
|
||||
roundToks := bytes.Split(saltToks[2], []byte{'='})
|
||||
cost, err := strconv.ParseInt(string(roundToks[1]), 10, 0)
|
||||
return int(cost), err
|
||||
}
|
||||
|
||||
func (c *crypter) SetSalt(salt common.Salt) { c.Salt = salt }
|
||||
|
||||
func GetSalt() common.Salt {
|
||||
return common.Salt{
|
||||
MagicPrefix: []byte(MagicPrefix),
|
||||
SaltLenMin: SaltLenMin,
|
||||
SaltLenMax: SaltLenMax,
|
||||
RoundsDefault: RoundsDefault,
|
||||
RoundsMin: RoundsMin,
|
||||
RoundsMax: RoundsMax,
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue