checking in prelim stuff
This commit is contained in:
226
kdf/funcs_bcrypt_pbkdf.go
Normal file
226
kdf/funcs_bcrypt_pbkdf.go
Normal file
@@ -0,0 +1,226 @@
|
||||
package kdf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
|
||||
bcryptPbkdf "github.com/dchest/bcrypt_pbkdf"
|
||||
"r00t2.io/sshkeys/internal"
|
||||
)
|
||||
|
||||
/*
|
||||
Setup must be called before DeriveKey. It configures a BcryptPbkdf.
|
||||
|
||||
If secret is nil or an empty byte slice, ErrNoSecret will be returned.
|
||||
|
||||
If salt is nil or an empty byte slice, one will be randomly generated of BcryptPbkdfDefaultSaltLen length.
|
||||
|
||||
If rounds is 0, BcryptPbkdfDefaultRounds will be used.
|
||||
|
||||
If keyLen is 0, BcryptPbkdfDefaultKeyLen will be used.
|
||||
*/
|
||||
func (b *BcryptPbkdf) Setup(secret, salt []byte, rounds, keyLen uint32) (err error) {
|
||||
|
||||
if secret == nil || len(secret) == 0 {
|
||||
err = ErrNoSecret
|
||||
return
|
||||
}
|
||||
|
||||
if salt == nil || len(salt) == 0 {
|
||||
salt = make([]byte, BcryptPbkdfDefaultSaltLen)
|
||||
if _, err = rand.Read(salt); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if rounds == 0 {
|
||||
rounds = BcryptPbkdfDefaultRounds
|
||||
}
|
||||
|
||||
if keyLen == 0 {
|
||||
keyLen = BcryptPbkdfDefaultKeyLen
|
||||
}
|
||||
|
||||
b.secret = secret
|
||||
b.salt = salt
|
||||
b.rounds = rounds
|
||||
b.keyLen = keyLen
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
SetupAuto is used to provide out-of-band configuration if the KDF options were found via GetKdfFromBytes.
|
||||
|
||||
You can test this by running KDF.AutoOK.
|
||||
*/
|
||||
func (b *BcryptPbkdf) SetupAuto(secret []byte, keyLen uint32) (err error) {
|
||||
|
||||
if !b.AutoOK() {
|
||||
err = ErrUnknownKdf
|
||||
return
|
||||
}
|
||||
|
||||
if keyLen == 0 {
|
||||
keyLen = BcryptPbkdfDefaultKeyLen
|
||||
}
|
||||
|
||||
b.secret = secret
|
||||
b.keyLen = keyLen
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
DeriveKey returns the derived key from a BcryptPbkdf.
|
||||
|
||||
It must be called *after* Setup.
|
||||
*/
|
||||
func (b *BcryptPbkdf) DeriveKey() (key []byte, err error) {
|
||||
|
||||
if b.secret == nil {
|
||||
err = ErrNoSecret
|
||||
return
|
||||
}
|
||||
if b.salt == nil {
|
||||
err = ErrNoSalt
|
||||
return
|
||||
}
|
||||
if b.rounds == 0 {
|
||||
err = ErrNoRounds
|
||||
return
|
||||
}
|
||||
if b.keyLen == 0 {
|
||||
err = ErrNoKeyLen
|
||||
}
|
||||
|
||||
if b.key, err = bcryptPbkdf.Key(b.secret, b.salt, int(b.rounds), int(b.keyLen)); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
key = b.key
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Name returns BcryptPbkdfName.
|
||||
func (b *BcryptPbkdf) Name() (name string) {
|
||||
|
||||
name = BcryptPbkdfName
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NameBytes returns the byte form of BcryptPbkdf.Name with leading bytecount allocator.
|
||||
func (b *BcryptPbkdf) NameBytes() (name []byte) {
|
||||
|
||||
var nb []byte
|
||||
var s string = b.Name()
|
||||
|
||||
nb = []byte(s)
|
||||
|
||||
name = make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(name, uint32(len(nb)))
|
||||
name = append(name, nb...)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// PackedBytes returns 3.0 and recursed.
|
||||
func (b *BcryptPbkdf) PackedBytes() (buf *bytes.Reader, err error) {
|
||||
|
||||
var rounds []byte = make([]byte, 4)
|
||||
var packer *bytes.Reader
|
||||
var w *bytes.Buffer = new(bytes.Buffer)
|
||||
|
||||
// 3.0.0.0 and 3.0.0.0.0
|
||||
if packer, err = internal.ReadSizeBytes(b.salt, true); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = packer.WriteTo(w); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 3.0.0.1
|
||||
binary.BigEndian.PutUint32(rounds, b.rounds)
|
||||
if _, err = w.Write(rounds); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 3.0
|
||||
if buf, err = internal.ReadSizeBytes(w, true); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Rounds returns the number of rounds used in derivation.
|
||||
func (b *BcryptPbkdf) Rounds() (rounds uint32) {
|
||||
|
||||
rounds = b.rounds
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Salt returns the salt bytes.
|
||||
func (b *BcryptPbkdf) Salt() (salt []byte) {
|
||||
|
||||
salt = b.salt
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
AutoOK returns true if a GetKdfFromBytes call was able to fetch the KDF options successfully, in which case the caller may use KDF.SetupAuto.
|
||||
|
||||
If false, it will need to be manually configured via KDF.Setup.
|
||||
*/
|
||||
func (b *BcryptPbkdf) AutoOK() (ok bool) {
|
||||
|
||||
ok = true
|
||||
|
||||
if b.salt == nil || len(b.salt) == 0 {
|
||||
ok = false
|
||||
}
|
||||
|
||||
if b.rounds == 0 {
|
||||
ok = false
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// IsPlain indicates if this KDF actually does derivation (false) or not (true).
|
||||
func (b *BcryptPbkdf) IsPlain() (plain bool) {
|
||||
|
||||
plain = false
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// addSalt adds a salt as parsed from GetKdfFromBytes.
|
||||
func (b *BcryptPbkdf) addSalt(salt []byte) (err error) {
|
||||
|
||||
if salt == nil || len(salt) == 0 {
|
||||
err = ErrNoSalt
|
||||
return
|
||||
}
|
||||
b.salt = salt
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// addRounds adds the rounds as parsed from GetKdfFromBytes
|
||||
func (b *BcryptPbkdf) addRounds(rounds uint32) (err error) {
|
||||
|
||||
if rounds == 0 {
|
||||
err = ErrNoRounds
|
||||
return
|
||||
}
|
||||
|
||||
b.rounds = rounds
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user