From fae43f12f846288c865c8750abb137dc169cb003 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Thu, 24 Oct 2024 05:14:13 -0700 Subject: [PATCH] Limit argon2 concurrency (#313) Control concurrent use of argon2, which is very cpu/ram intensive. Running concurrent operations most often provides no benefit anyway, since it already uses 32 threads. We simply hold a package level mutex while deriving the key. --- encrypt.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/encrypt.go b/encrypt.go index 7ae6574..98d52f6 100644 --- a/encrypt.go +++ b/encrypt.go @@ -24,6 +24,7 @@ import ( "crypto/sha256" "errors" "io" + "sync" "github.com/secure-io/sio-go" "github.com/secure-io/sio-go/sioutil" @@ -63,7 +64,9 @@ func EncryptData(password string, data []byte) ([]byte, error) { } id = pbkdf2AESGCM } else { + argon2Mu.Lock() key := argon2.IDKey([]byte(password), salt, argon2idTime, argon2idMemory, argon2idThreads, 32) + argon2Mu.Unlock() if sioutil.NativeAES() { stream, err = sio.AES_256_GCM.Stream(key) if err != nil { @@ -100,6 +103,12 @@ func EncryptData(password string, data []byte) ([]byte, error) { return ciphertext.Bytes(), nil } +// argon2Mu is used to control concurrent use of argon2, +// which is very cpu/ram intensive. +// Running concurrent operations most often provides no benefit anyway, +// since it already uses 32 threads. +var argon2Mu sync.Mutex + // ErrMaliciousData indicates that the stream cannot be // decrypted by provided credentials. var ErrMaliciousData = sio.NotAuthentic @@ -132,10 +141,14 @@ func DecryptData(password string, data io.Reader) ([]byte, error) { ) switch { case id[0] == argon2idAESGCM: + argon2Mu.Lock() key := argon2.IDKey([]byte(password), salt, argon2idTime, argon2idMemory, argon2idThreads, 32) + argon2Mu.Unlock() stream, err = sio.AES_256_GCM.Stream(key) case id[0] == argon2idChaCHa20Poly1305: + argon2Mu.Lock() key := argon2.IDKey([]byte(password), salt, argon2idTime, argon2idMemory, argon2idThreads, 32) + argon2Mu.Unlock() stream, err = sio.ChaCha20Poly1305.Stream(key) case id[0] == pbkdf2AESGCM: key := pbkdf2.Key([]byte(password), salt, pbkdf2Cost, 32, sha256.New)