@@ -420,3 +420,31 @@ func GenerateRSAKeyWithExponent(bits int, exponent int) (PrivateKey, error) {
420420 })
421421 return p , nil
422422}
423+
424+ // DeriveKey generates a key and IV from given password and salt using openssl EVP_BytesToKey()
425+ func DeriveKey (cipher * Cipher , digest * Digest , salt []byte , password []byte ,
426+ iterations int ) (key , iv []byte , err error ) {
427+ key = make ([]byte , cipher .KeySize ())
428+ iv = make ([]byte , cipher .IVSize ())
429+
430+ var saltPtr , ivPtr , passwordPtr , keyPtr * C.uchar
431+ if len (salt ) != 0 {
432+ saltPtr = (* C .uchar )(unsafe .Pointer (& salt [0 ]))
433+ }
434+ if len (iv ) != 0 {
435+ ivPtr = (* C .uchar )(unsafe .Pointer (& iv [0 ]))
436+ }
437+ if iterations < 1 {
438+ return nil , nil , errors .New ("iterations count must be 1 or greater" )
439+ }
440+ passwordSize := C .int (len (password ))
441+ passwordPtr = (* C .uchar )(unsafe .Pointer (& password [0 ]))
442+ keyPtr = (* C .uchar )(unsafe .Pointer (& key [0 ]))
443+
444+ derivedKeySize := C .EVP_BytesToKey (cipher .ptr , digest .ptr , saltPtr ,
445+ passwordPtr , passwordSize , C .int (iterations ), keyPtr , ivPtr )
446+ if derivedKeySize != C .int (cipher .KeySize ()) {
447+ return nil , nil , errors .New ("key derivation failed" )
448+ }
449+ return key , iv , nil
450+ }
0 commit comments