diff --git a/scrypt.go b/scrypt.go new file mode 100644 index 0000000..e8da60f --- /dev/null +++ b/scrypt.go @@ -0,0 +1,37 @@ +//go:build !cmd_go_bootstrap + +package openssl + +// #include "goopenssl.h" +import "C" +import ( + "unsafe" +) + +func Scrypt(password string, salt []byte, N, r, p, maxmem, keylen uint64) ([]byte, error) { + cpassword := C.CString(password) + defer C.free((unsafe.Pointer)(cpassword)) + + csalt := C.CBytes(salt) + defer C.free((unsafe.Pointer)(csalt)) + + key := C.malloc(C.size_t(keylen)) + defer C.free(key) + + res := C.go_openssl_EVP_PBE_scrypt( + cpassword, + C.size_t(len(password)), + (*C.uchar)(csalt), + C.size_t(len(salt)), + C.uint64_t(N), + C.uint64_t(r), + C.uint64_t(p), + C.uint64_t(maxmem), + (*C.uchar)(key), + C.size_t(keylen), + ) + if res != 1 { + return nil, newOpenSSLError("EVP_PBE_scrypt") + } + return C.GoBytes(key, C.int(keylen)), nil +} diff --git a/scrypt_test.go b/scrypt_test.go new file mode 100644 index 0000000..59609b7 --- /dev/null +++ b/scrypt_test.go @@ -0,0 +1,36 @@ +//go:build !cmd_go_bootstrap + +package openssl_test + +import ( + "fmt" + "testing" + + "github.com/golang-fips/openssl/v2" +) + +func TestScrypt(t *testing.T) { + hash, err := openssl.Scrypt("testpass01", []byte("abc123"), 1<<14, 8, 1, 32<<20, 64) + if err != nil { + t.Fatal(err) + } + if len(hash) == 0 { + t.Error("zero length hash") + } + hexhash := fmt.Sprintf("%x", hash) + exp := "e6a3569950bf90e88d2f114c3d43f2d103cf3c13cf1579095e88ff5b3b3eb379cad31d26aa533e0f32c10666bbcc9c1cac2775a8a60d55d55d63c401927e905e" + if hexhash != exp { + t.Errorf("expected %q, got %q", exp, hexhash) + } +} + +func TestScrypt_Err(t *testing.T) { + _, err := openssl.Scrypt("testpass01", []byte("abc123"), 1<<14, 0, 0, 32<<20, 64) + if err == nil { + t.Error("expected an error when using zeros for r and p") + } + _, err = openssl.Scrypt("x", []byte("y"), 1<<14, 8, 1, 1<<20, 32) + if err == nil { + t.Error("expected memory limit error") + } +} diff --git a/shims.h b/shims.h index 437312a..c26ed95 100644 --- a/shims.h +++ b/shims.h @@ -410,4 +410,4 @@ DEFINEFUNC_3_0(int, EVP_KDF_CTX_set_params, (GO_EVP_KDF_CTX_PTR ctx, const GO_OS DEFINEFUNC_3_0(void, EVP_KDF_CTX_free, (GO_EVP_KDF_CTX_PTR ctx), (ctx)) \ DEFINEFUNC_3_0(size_t, EVP_KDF_CTX_get_kdf_size, (GO_EVP_KDF_CTX_PTR ctx), (ctx)) \ DEFINEFUNC_3_0(int, EVP_KDF_derive, (GO_EVP_KDF_CTX_PTR ctx, unsigned char *key, size_t keylen, const GO_OSSL_PARAM_PTR params), (ctx, key, keylen, params)) \ - +DEFINEFUNC_1_1_1(int, EVP_PBE_scrypt, (const char *pass, size_t passlen, const unsigned char *salt, size_t saltlen, uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, unsigned char *key, size_t keylen), (pass, passlen, salt, saltlen, N, r, p, maxmem, key, keylen))