diff --git a/key.go b/key.go index 58fb120b..9300e719 100644 --- a/key.go +++ b/key.go @@ -420,3 +420,29 @@ func GenerateRSAKeyWithExponent(bits int, exponent int) (PrivateKey, error) { }) return p, nil } + +// DeriveKey generates a key and IV from given password and salt using openssl EVB_BytesToKey() +func DeriveKey(cipher *Cipher, digest *Digest, salt []byte, password string, iterations int) (key, iv []byte, err error) { + key = make([]byte, cipher.KeySize()) + iv = make([]byte, cipher.IVSize()) + + var saltPtr, ivPtr, passwordPtr, keyPtr *C.uchar + if len(salt) != 0 && salt != nil { + saltPtr = (*C.uchar)(unsafe.Pointer(&salt[0])) + } + if len(iv) != 0 && iv != nil { + ivPtr = (*C.uchar)(unsafe.Pointer(&iv[0])) + } + if iterations < 1 { + return nil, nil, errors.New("iterations count must be 1 or greater") + } + passwordSize := C.int(len([]byte(password))) + passwordPtr = (*C.uchar)(unsafe.Pointer(&([]byte(password))[0])) + keyPtr = (*C.uchar)(unsafe.Pointer(&key[0])) + + derivedKeySize := C.EVP_BytesToKey(cipher.ptr, digest.ptr, saltPtr, passwordPtr, passwordSize, C.int(iterations), keyPtr, ivPtr) + if derivedKeySize != C.int(cipher.KeySize()) { + return nil, nil, errors.New("key derivation failed") + } + return +}