first draft of atheme migration code

This commit is contained in:
Shivaram Lingamneni
2020-10-02 16:48:37 -04:00
parent c060113c74
commit 7a6413ea2c
25 changed files with 1423 additions and 63 deletions

59
vendor/github.com/GehirnInc/crypt/common/base64.go generated vendored Normal file
View File

@@ -0,0 +1,59 @@
// (C) Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>. 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) []byte {
if len(src) == 0 {
return []byte{} // TODO: return nil
}
dstlen := (len(src)*8 + 5) / 6
dst := make([]byte, dstlen)
di, si := 0, 0
n := len(src) / 3 * 3
for si < n {
val := uint(src[si+2])<<16 | uint(src[si+1])<<8 | uint(src[si])
dst[di+0] = alphabet[val&0x3f]
dst[di+1] = alphabet[val>>6&0x3f]
dst[di+2] = alphabet[val>>12&0x3f]
dst[di+3] = alphabet[val>>18]
di += 4
si += 3
}
rem := len(src) - si
if rem == 0 {
return dst
}
val := uint(src[si+0])
if rem == 2 {
val |= uint(src[si+1]) << 8
}
dst[di+0] = alphabet[val&0x3f]
dst[di+1] = alphabet[val>>6&0x3f]
if rem == 2 {
dst[di+2] = alphabet[val>>12]
}
return dst
}

10
vendor/github.com/GehirnInc/crypt/common/doc.go generated vendored Normal file
View File

@@ -0,0 +1,10 @@
// (C) Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>. 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

148
vendor/github.com/GehirnInc/crypt/common/salt.go generated vendored Normal file
View File

@@ -0,0 +1,148 @@
// (C) Copyright 2012, Jeramey Crawford <jeramey@antihe.ro>. 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 (
"bytes"
"crypto/rand"
"errors"
"strconv"
)
var (
ErrSaltPrefix = errors.New("invalid magic prefix")
ErrSaltFormat = errors.New("invalid salt format")
ErrSaltRounds = errors.New("invalid rounds")
)
const (
roundsPrefix = "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 += 1
}
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 += 1
}
salt := make([]byte, saltLen)
rand.Read(salt)
roundsText := ""
if rounds != s.RoundsDefault {
roundsText = roundsPrefix + 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
}
func (s *Salt) Decode(raw []byte) (salt []byte, rounds int, isRoundsDef bool, rest []byte, err error) {
tokens := bytes.SplitN(raw, []byte{'$'}, 4)
if len(tokens) < 3 {
err = ErrSaltFormat
return
}
if !bytes.HasPrefix(raw, s.MagicPrefix) {
err = ErrSaltPrefix
return
}
if bytes.HasPrefix(tokens[2], []byte(roundsPrefix)) {
if len(tokens) < 4 {
err = ErrSaltFormat
return
}
salt = tokens[3]
rounds, err = strconv.Atoi(string(tokens[2][len(roundsPrefix):]))
if err != nil {
err = ErrSaltRounds
return
}
if rounds < s.RoundsMin {
rounds = s.RoundsMin
}
if rounds > s.RoundsMax {
rounds = s.RoundsMax
}
isRoundsDef = true
} else {
salt = tokens[2]
rounds = s.RoundsDefault
}
if len(salt) > s.SaltLenMax {
salt = salt[0:s.SaltLenMax]
}
return
}