go-crypt/crypt/kdf.go
Snider 62482c7dc9
Some checks failed
Security Scan / security (pull_request) Failing after 9s
Test / test (pull_request) Failing after 8m29s
refactor: migrate imports to dappco.re/go/core/* paths
Update module path from forge.lthn.ai/core/go-crypt to
dappco.re/go/core/crypt. Migrate go-log, go-io, go-i18n imports to
their new dappco.re/go/core/* paths with updated versions (core v0.5.0,
log v0.1.0, io v0.2.0, i18n v0.2.0). Un-migrated modules (cli,
go-store, go-inference) remain at forge.lthn.ai paths.

Also fixes merge conflict marker and duplicate imports in
crypt/openpgp/service.go, and updates CLAUDE.md to reflect new paths.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 01:43:27 +00:00

61 lines
1.9 KiB
Go

// Package crypt provides cryptographic utilities including encryption,
// hashing, key derivation, HMAC, and checksum functions.
package crypt
import (
"crypto/rand"
"crypto/sha256"
"io"
coreerr "dappco.re/go/core/log"
"golang.org/x/crypto/argon2"
"golang.org/x/crypto/hkdf"
"golang.org/x/crypto/scrypt"
)
// Argon2id default parameters.
const (
argon2Memory = 64 * 1024 // 64 MB
argon2Time = 3
argon2Parallelism = 4
argon2KeyLen = 32
argon2SaltLen = 16
)
// DeriveKey derives a key from a passphrase using Argon2id with default parameters.
// The salt must be argon2SaltLen bytes. keyLen specifies the desired key length.
func DeriveKey(passphrase, salt []byte, keyLen uint32) []byte {
return argon2.IDKey(passphrase, salt, argon2Time, argon2Memory, argon2Parallelism, keyLen)
}
// DeriveKeyScrypt derives a key from a passphrase using scrypt.
// Uses recommended parameters: N=32768, r=8, p=1.
func DeriveKeyScrypt(passphrase, salt []byte, keyLen int) ([]byte, error) {
key, err := scrypt.Key(passphrase, salt, 32768, 8, 1, keyLen)
if err != nil {
return nil, coreerr.E("crypt.DeriveKeyScrypt", "failed to derive key", err)
}
return key, nil
}
// HKDF derives a key using HKDF-SHA256.
// secret is the input keying material, salt is optional (can be nil),
// info is optional context, and keyLen is the desired output length.
func HKDF(secret, salt, info []byte, keyLen int) ([]byte, error) {
reader := hkdf.New(sha256.New, secret, salt, info)
key := make([]byte, keyLen)
if _, err := io.ReadFull(reader, key); err != nil {
return nil, coreerr.E("crypt.HKDF", "failed to derive key", err)
}
return key, nil
}
// generateSalt creates a random salt of the given length.
func generateSalt(length int) ([]byte, error) {
salt := make([]byte, length)
if _, err := rand.Read(salt); err != nil {
return nil, coreerr.E("crypt.generateSalt", "failed to generate random salt", err)
}
return salt, nil
}