forked from External/ergo
first draft of atheme migration code
This commit is contained in:
parent
c060113c74
commit
7a6413ea2c
25 changed files with 1423 additions and 63 deletions
143
vendor/github.com/GehirnInc/crypt/md5_crypt/md5_crypt.go
generated
vendored
Normal file
143
vendor/github.com/GehirnInc/crypt/md5_crypt/md5_crypt.go
generated
vendored
Normal 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 }
|
||||
Loading…
Add table
Add a link
Reference in a new issue