@@ -420,3 +420,31 @@ func GenerateRSAKeyWithExponent(bits int, exponent int) (PrivateKey, error) {
420
420
})
421
421
return p , nil
422
422
}
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