package storage import ( "crypto/rand" "golang.org/x/crypto/argon2" ) const ( argon2Time uint32 = 1 argon2Memory uint32 = 64 * 1024 // 64 MB — RFC 9106 Section 7.3 argon2Threads uint8 = 4 argon2KeyLen uint32 = 32 // AES-256 key length saltSize = 16 ) // DeriveKey produces a 32-byte AES-256 key from a passphrase and salt using Argon2id. // Uses RFC 9106 Section 7.3 recommended parameters. // Given the same passphrase and salt, always returns the same key. func DeriveKey(passphrase []byte, salt []byte) []byte { return argon2.IDKey(passphrase, salt, argon2Time, argon2Memory, argon2Threads, argon2KeyLen) } // NewSalt generates a cryptographically random 16-byte salt. // Store alongside the database and reuse on each key derivation. func NewSalt() ([]byte, error) { salt := make([]byte, saltSize) if _, err := rand.Read(salt); err != nil { return nil, err } return salt, nil }