mirror of
https://github.com/Luzifer/go-openssl.git
synced 2024-12-21 03:11:18 +00:00
59 lines
1.8 KiB
Go
59 lines
1.8 KiB
Go
|
package openssl
|
||
|
|
||
|
import (
|
||
|
"crypto/md5"
|
||
|
"crypto/sha1"
|
||
|
"crypto/sha256"
|
||
|
"hash"
|
||
|
|
||
|
"golang.org/x/crypto/pbkdf2"
|
||
|
)
|
||
|
|
||
|
const DefaultPBKDF2Iterations = 10000
|
||
|
|
||
|
// CredsGenerator are functions to derive a key and iv from a password and a salt
|
||
|
type CredsGenerator func(password, salt []byte) (Creds, error)
|
||
|
|
||
|
var (
|
||
|
BytesToKeyMD5 = NewBytesToKeyGenerator(md5.New)
|
||
|
BytesToKeySHA1 = NewBytesToKeyGenerator(sha1.New)
|
||
|
BytesToKeySHA256 = NewBytesToKeyGenerator(sha256.New)
|
||
|
PBKDF2MD5 = NewPBKDF2Generator(md5.New, DefaultPBKDF2Iterations)
|
||
|
PBKDF2SHA1 = NewPBKDF2Generator(sha1.New, DefaultPBKDF2Iterations)
|
||
|
PBKDF2SHA256 = NewPBKDF2Generator(sha256.New, DefaultPBKDF2Iterations)
|
||
|
)
|
||
|
|
||
|
// openSSLEvpBytesToKey follows the OpenSSL (undocumented?) convention for extracting the key and IV from passphrase.
|
||
|
// It uses the EVP_BytesToKey() method which is basically:
|
||
|
// D_i = HASH^count(D_(i-1) || password || salt) where || denotes concatentaion, until there are sufficient bytes available
|
||
|
// 48 bytes since we're expecting to handle AES-256, 32bytes for a key and 16bytes for the IV
|
||
|
func NewBytesToKeyGenerator(hashFunc func() hash.Hash) CredsGenerator {
|
||
|
df := func(in []byte) []byte {
|
||
|
h := hashFunc()
|
||
|
h.Write(in)
|
||
|
return h.Sum(nil)
|
||
|
}
|
||
|
|
||
|
return func(password, salt []byte) (Creds, error) {
|
||
|
var m []byte
|
||
|
prev := []byte{}
|
||
|
for len(m) < 48 {
|
||
|
a := make([]byte, len(prev)+len(password)+len(salt))
|
||
|
copy(a, prev)
|
||
|
copy(a[len(prev):], password)
|
||
|
copy(a[len(prev)+len(password):], salt)
|
||
|
|
||
|
prev = df(a)
|
||
|
m = append(m, prev...)
|
||
|
}
|
||
|
return Creds{Key: m[:32], IV: m[32:48]}, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func NewPBKDF2Generator(hashFunc func() hash.Hash, iterations int) CredsGenerator {
|
||
|
return func(password, salt []byte) (Creds, error) {
|
||
|
m := pbkdf2.Key(password, salt, iterations, 32+16, hashFunc)
|
||
|
return Creds{Key: m[:32], IV: m[32:48]}, nil
|
||
|
}
|
||
|
}
|