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

7
vendor/github.com/GehirnInc/crypt/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,7 @@
language: go
go:
- 1.6.x
- 1.7.x
- master
script:
- go test -v -race ./...

8
vendor/github.com/GehirnInc/crypt/AUTHORS.md generated vendored Normal file
View file

@ -0,0 +1,8 @@
### Initial author
[Jeramey Crawford](https://github.com/jeramey)
### Other authors
- [Jonas mg](https://github.com/kless)
- [Kohei YOSHIDA](https://github.com/yosida95)

26
vendor/github.com/GehirnInc/crypt/LICENSE generated vendored Normal file
View file

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

61
vendor/github.com/GehirnInc/crypt/README.rst generated vendored Normal file
View file

@ -0,0 +1,61 @@
.. image:: https://travis-ci.org/GehirnInc/crypt.svg?branch=master
:target: https://travis-ci.org/GehirnInc/crypt
crypt - A password hashing library for Go
=========================================
crypt provides pure golang implementations of UNIX's crypt(3).
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!
Install
-------
To install crypt, use the *go get* command.
.. code-block:: sh
go get github.com/GehirnInc/crypt
Usage
-----
.. code-block:: go
package main
import (
"fmt"
"github.com/GehirnInc/crypt"
_ "github.com/GehirnInc/crypt/sha256_crypt"
)
func main() {
crypt := crypt.SHA256.New()
ret, _ := crypt.Generate([]byte("secret"), []byte("$5$salt"))
fmt.Println(ret)
err := crypt.Verify(ret, []byte("secret"))
fmt.Println(err)
// Output:
// $5$salt$kpa26zwgX83BPSR8d7w93OIXbFt/d3UOTZaAu5vsTM6
// <nil>
}
Documentation
-------------
The documentation is available on GoDoc_.
.. _GoDoc: https://godoc.org/github.com/GehirnInc/crypt

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
}

121
vendor/github.com/GehirnInc/crypt/crypt.go generated vendored Normal file
View file

@ -0,0 +1,121 @@
// (C) 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/GehirnInc/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 = 1 + iota // import github.com/GehirnInc/crypt/apr1_crypt
MD5 // import github.com/GehirnInc/crypt/md5_crypt
SHA256 // import github.com/GehirnInc/crypt/sha256_crypt
SHA512 // import github.com/GehirnInc/crypt/sha512_crypt
maxCrypt
)
var crypts = make([]func() Crypter, maxCrypt)
// New returns new Crypter making the Crypt c.
// New panics if the Crypt c is unavailable.
func (c Crypt) New() Crypter {
if c > 0 && c < maxCrypt {
f := crypts[c]
if f != nil {
return f()
}
}
panic("crypt: requested crypt function is unavailable")
}
// Available reports whether the Crypt c is available.
func (c Crypt) Available() bool {
return c > 0 && c < maxCrypt && crypts[c] != nil
}
var cryptPrefixes = make([]string, 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 {
return c.New()
}
// IsHashSupported returns true if hashedKey has a supported prefix.
// NewFromHash will not panic for this hashedKey
func IsHashSupported(hashedKey string) bool {
for i := range cryptPrefixes {
prefix := cryptPrefixes[i]
if crypts[i] != nil && strings.HasPrefix(hashedKey, prefix) {
return true
}
}
return false
}
// NewFromHash returns a new Crypter using the prefix in the given hashed key.
func NewFromHash(hashedKey string) Crypter {
for i := range cryptPrefixes {
prefix := cryptPrefixes[i]
if crypts[i] != nil && strings.HasPrefix(hashedKey, prefix) {
crypt := Crypt(uint(i))
return crypt.New()
}
}
panic("crypt: unknown crypt function")
}

41
vendor/github.com/GehirnInc/crypt/internal/utils.go generated vendored Normal file
View file

@ -0,0 +1,41 @@
// Copyright (c) 2015 Kohei YOSHIDA. All rights reserved.
// This software is licensed under the 3-Clause BSD License
// that can be found in LICENSE file.
package internal
const (
cleanBytesLen = 64
)
var (
cleanBytes = make([]byte, cleanBytesLen)
)
func CleanSensitiveData(b []byte) {
l := len(b)
for ; l > cleanBytesLen; l -= cleanBytesLen {
copy(b[l-cleanBytesLen:l], cleanBytes)
}
if l > 0 {
copy(b[0:l], cleanBytes[0:l])
}
}
func RepeatByteSequence(input []byte, length int) []byte {
var (
sequence = make([]byte, length)
unit = len(input)
)
j := length / unit * unit
for i := 0; i < j; i += unit {
copy(sequence[i:length], input)
}
if j < length {
copy(sequence[j:length], input[0:length-j])
}
return sequence
}

View file

@ -0,0 +1,143 @@
// (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 md5_crypt implements the standard Unix MD5-crypt algorithm created by
// Poul-Henning Kamp for FreeBSD.
package md5_crypt
import (
"bytes"
"crypto/md5"
"crypto/subtle"
"github.com/GehirnInc/crypt"
"github.com/GehirnInc/crypt/common"
"github.com/GehirnInc/crypt/internal"
)
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{
common.Salt{
MagicPrefix: []byte(MagicPrefix),
SaltLenMin: SaltLenMin,
SaltLenMax: SaltLenMax,
RoundsDefault: RoundsDefault,
},
}
}
func (c *crypter) Generate(key, salt []byte) (result string, err error) {
if len(salt) == 0 {
salt = c.Salt.Generate(SaltLenMax)
}
salt, _, _, _, err = c.Salt.Decode(salt)
if err != nil {
return
}
keyLen := len(key)
h := md5.New()
// Compute sumB
h.Write(key)
h.Write(salt)
h.Write(key)
sumB := h.Sum(nil)
// Compute sumA
h.Reset()
h.Write(key)
h.Write(c.Salt.MagicPrefix)
h.Write(salt)
h.Write(internal.RepeatByteSequence(sumB, keyLen))
// 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 := keyLen; i > 0; i >>= 1 {
if i%2 == 0 {
h.Write(key[0:1])
} else {
h.Write([]byte{0})
}
}
sumA := h.Sum(nil)
internal.CleanSensitiveData(sumB)
// 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++ {
h.Reset()
// Add key or last result.
if i%2 != 0 {
h.Write(key)
} else {
h.Write(sumA)
}
// Add salt for numbers not divisible by 3.
if i%3 != 0 {
h.Write(salt)
}
// Add key for numbers not divisible by 7.
if i%7 != 0 {
h.Write(key)
}
// Add key or last result.
if i&1 != 0 {
h.Write(sumA)
} else {
h.Write(key)
}
copy(sumA, h.Sum(nil))
}
buf := bytes.Buffer{}
buf.Grow(len(c.Salt.MagicPrefix) + len(salt) + 1 + 22)
buf.Write(c.Salt.MagicPrefix)
buf.Write(salt)
buf.WriteByte('$')
buf.Write(common.Base64_24Bit([]byte{
sumA[12], sumA[6], sumA[0],
sumA[13], sumA[7], sumA[1],
sumA[14], sumA[8], sumA[2],
sumA[15], sumA[9], sumA[3],
sumA[5], sumA[10], sumA[4],
sumA[11],
}))
return buf.String(), nil
}
func (c *crypter) Verify(hashedKey string, key []byte) error {
newHash, err := c.Generate(key, []byte(hashedKey))
if err != nil {
return err
}
if subtle.ConstantTimeCompare([]byte(newHash), []byte(hashedKey)) != 1 {
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 }