Merge pull request '[agent/claude:opus] DX audit and fix. 1) Review CLAUDE.md — update any outdate...' (#3) from agent/dx-audit-and-fix--1--review-claude-md into main
Some checks failed
Security Scan / security (push) Failing after 8s
Test / test (push) Successful in 1m15s

This commit is contained in:
Virgil 2026-03-17 08:03:20 +00:00
commit e691a9ce51
8 changed files with 65 additions and 65 deletions

View file

@ -59,8 +59,8 @@ No C toolchain or CGo required — all crypto uses pure Go implementations.
- **Tests**: testify assert/require, `_Good`/`_Bad`/`_Ugly` naming convention - **Tests**: testify assert/require, `_Good`/`_Bad`/`_Ugly` naming convention
- **Concurrency tests**: 10 goroutines via WaitGroup; must pass `-race` - **Concurrency tests**: 10 goroutines via WaitGroup; must pass `-race`
- **Imports**: stdlib → forge.lthn.ai → third-party, separated by blank lines - **Imports**: stdlib → forge.lthn.ai → third-party, separated by blank lines
- **Errors**: use `core.E("package.Function", "lowercase message", err)` (imported - **Errors**: use `coreerr.E("package.Function", "lowercase message", err)` (imported
from `forge.lthn.ai/core/go-log`); never include secrets in error strings as `coreerr "forge.lthn.ai/core/go-log"`); never include secrets in error strings
- **Randomness**: `crypto/rand` only; never `math/rand` - **Randomness**: `crypto/rand` only; never `math/rand`
- **Conventional commits**: `feat(auth):`, `fix(crypt):`, `refactor(trust):` - **Conventional commits**: `feat(auth):`, `fix(crypt):`, `refactor(trust):`
Scopes match package names: `auth`, `crypt`, `trust`, `pgp`, `lthn`, `rsa`, Scopes match package names: `auth`, `crypt`, `trust`, `pgp`, `lthn`, `rsa`,

View file

@ -171,15 +171,15 @@ func formatCoverage(cov float64) string {
} }
func shortenPackageName(name string) string { func shortenPackageName(name string) string {
// Remove common prefixes const forgePrefix = "forge.lthn.ai/core/"
prefixes := []string{ if strings.HasPrefix(name, forgePrefix) {
"forge.lthn.ai/core/cli/", remainder := strings.TrimPrefix(name, forgePrefix)
"forge.lthn.ai/core/gui/", // If there's a sub-path (e.g. "go/pkg/foo"), strip the module name
} if idx := strings.Index(remainder, "/"); idx >= 0 {
for _, prefix := range prefixes { return remainder[idx+1:]
if strings.HasPrefix(name, prefix) {
return strings.TrimPrefix(name, prefix)
} }
// Module root (e.g. "cli-php") — return as-is
return remainder
} }
return filepath.Base(name) return filepath.Base(name)
} }

View file

@ -7,20 +7,20 @@ import (
"io" "io"
"os" "os"
core "forge.lthn.ai/core/go-log" coreerr "forge.lthn.ai/core/go-log"
) )
// SHA256File computes the SHA-256 checksum of a file and returns it as a hex string. // SHA256File computes the SHA-256 checksum of a file and returns it as a hex string.
func SHA256File(path string) (string, error) { func SHA256File(path string) (string, error) {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {
return "", core.E("crypt.SHA256File", "failed to open file", err) return "", coreerr.E("crypt.SHA256File", "failed to open file", err)
} }
defer func() { _ = f.Close() }() defer func() { _ = f.Close() }()
h := sha256.New() h := sha256.New()
if _, err := io.Copy(h, f); err != nil { if _, err := io.Copy(h, f); err != nil {
return "", core.E("crypt.SHA256File", "failed to read file", err) return "", coreerr.E("crypt.SHA256File", "failed to read file", err)
} }
return hex.EncodeToString(h.Sum(nil)), nil return hex.EncodeToString(h.Sum(nil)), nil
@ -30,13 +30,13 @@ func SHA256File(path string) (string, error) {
func SHA512File(path string) (string, error) { func SHA512File(path string) (string, error) {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {
return "", core.E("crypt.SHA512File", "failed to open file", err) return "", coreerr.E("crypt.SHA512File", "failed to open file", err)
} }
defer func() { _ = f.Close() }() defer func() { _ = f.Close() }()
h := sha512.New() h := sha512.New()
if _, err := io.Copy(h, f); err != nil { if _, err := io.Copy(h, f); err != nil {
return "", core.E("crypt.SHA512File", "failed to read file", err) return "", coreerr.E("crypt.SHA512File", "failed to read file", err)
} }
return hex.EncodeToString(h.Sum(nil)), nil return hex.EncodeToString(h.Sum(nil)), nil

View file

@ -1,7 +1,7 @@
package crypt package crypt
import ( import (
core "forge.lthn.ai/core/go-log" coreerr "forge.lthn.ai/core/go-log"
) )
// Encrypt encrypts data with a passphrase using ChaCha20-Poly1305. // Encrypt encrypts data with a passphrase using ChaCha20-Poly1305.
@ -10,14 +10,14 @@ import (
func Encrypt(plaintext, passphrase []byte) ([]byte, error) { func Encrypt(plaintext, passphrase []byte) ([]byte, error) {
salt, err := generateSalt(argon2SaltLen) salt, err := generateSalt(argon2SaltLen)
if err != nil { if err != nil {
return nil, core.E("crypt.Encrypt", "failed to generate salt", err) return nil, coreerr.E("crypt.Encrypt", "failed to generate salt", err)
} }
key := DeriveKey(passphrase, salt, argon2KeyLen) key := DeriveKey(passphrase, salt, argon2KeyLen)
encrypted, err := ChaCha20Encrypt(plaintext, key) encrypted, err := ChaCha20Encrypt(plaintext, key)
if err != nil { if err != nil {
return nil, core.E("crypt.Encrypt", "failed to encrypt", err) return nil, coreerr.E("crypt.Encrypt", "failed to encrypt", err)
} }
// Prepend salt to the encrypted data (which already has nonce prepended) // Prepend salt to the encrypted data (which already has nonce prepended)
@ -31,7 +31,7 @@ func Encrypt(plaintext, passphrase []byte) ([]byte, error) {
// Expects format: salt (16 bytes) + nonce (24 bytes) + ciphertext. // Expects format: salt (16 bytes) + nonce (24 bytes) + ciphertext.
func Decrypt(ciphertext, passphrase []byte) ([]byte, error) { func Decrypt(ciphertext, passphrase []byte) ([]byte, error) {
if len(ciphertext) < argon2SaltLen { if len(ciphertext) < argon2SaltLen {
return nil, core.E("crypt.Decrypt", "ciphertext too short", nil) return nil, coreerr.E("crypt.Decrypt", "ciphertext too short", nil)
} }
salt := ciphertext[:argon2SaltLen] salt := ciphertext[:argon2SaltLen]
@ -41,7 +41,7 @@ func Decrypt(ciphertext, passphrase []byte) ([]byte, error) {
plaintext, err := ChaCha20Decrypt(encrypted, key) plaintext, err := ChaCha20Decrypt(encrypted, key)
if err != nil { if err != nil {
return nil, core.E("crypt.Decrypt", "failed to decrypt", err) return nil, coreerr.E("crypt.Decrypt", "failed to decrypt", err)
} }
return plaintext, nil return plaintext, nil
@ -53,14 +53,14 @@ func Decrypt(ciphertext, passphrase []byte) ([]byte, error) {
func EncryptAES(plaintext, passphrase []byte) ([]byte, error) { func EncryptAES(plaintext, passphrase []byte) ([]byte, error) {
salt, err := generateSalt(argon2SaltLen) salt, err := generateSalt(argon2SaltLen)
if err != nil { if err != nil {
return nil, core.E("crypt.EncryptAES", "failed to generate salt", err) return nil, coreerr.E("crypt.EncryptAES", "failed to generate salt", err)
} }
key := DeriveKey(passphrase, salt, argon2KeyLen) key := DeriveKey(passphrase, salt, argon2KeyLen)
encrypted, err := AESGCMEncrypt(plaintext, key) encrypted, err := AESGCMEncrypt(plaintext, key)
if err != nil { if err != nil {
return nil, core.E("crypt.EncryptAES", "failed to encrypt", err) return nil, coreerr.E("crypt.EncryptAES", "failed to encrypt", err)
} }
result := make([]byte, 0, len(salt)+len(encrypted)) result := make([]byte, 0, len(salt)+len(encrypted))
@ -73,7 +73,7 @@ func EncryptAES(plaintext, passphrase []byte) ([]byte, error) {
// Expects format: salt (16 bytes) + nonce (12 bytes) + ciphertext. // Expects format: salt (16 bytes) + nonce (12 bytes) + ciphertext.
func DecryptAES(ciphertext, passphrase []byte) ([]byte, error) { func DecryptAES(ciphertext, passphrase []byte) ([]byte, error) {
if len(ciphertext) < argon2SaltLen { if len(ciphertext) < argon2SaltLen {
return nil, core.E("crypt.DecryptAES", "ciphertext too short", nil) return nil, coreerr.E("crypt.DecryptAES", "ciphertext too short", nil)
} }
salt := ciphertext[:argon2SaltLen] salt := ciphertext[:argon2SaltLen]
@ -83,7 +83,7 @@ func DecryptAES(ciphertext, passphrase []byte) ([]byte, error) {
plaintext, err := AESGCMDecrypt(encrypted, key) plaintext, err := AESGCMDecrypt(encrypted, key)
if err != nil { if err != nil {
return nil, core.E("crypt.DecryptAES", "failed to decrypt", err) return nil, coreerr.E("crypt.DecryptAES", "failed to decrypt", err)
} }
return plaintext, nil return plaintext, nil

View file

@ -6,7 +6,7 @@ import (
"fmt" "fmt"
"strings" "strings"
core "forge.lthn.ai/core/go-log" coreerr "forge.lthn.ai/core/go-log"
"golang.org/x/crypto/argon2" "golang.org/x/crypto/argon2"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
@ -16,7 +16,7 @@ import (
func HashPassword(password string) (string, error) { func HashPassword(password string) (string, error) {
salt, err := generateSalt(argon2SaltLen) salt, err := generateSalt(argon2SaltLen)
if err != nil { if err != nil {
return "", core.E("crypt.HashPassword", "failed to generate salt", err) return "", coreerr.E("crypt.HashPassword", "failed to generate salt", err)
} }
hash := argon2.IDKey([]byte(password), salt, argon2Time, argon2Memory, argon2Parallelism, argon2KeyLen) hash := argon2.IDKey([]byte(password), salt, argon2Time, argon2Memory, argon2Parallelism, argon2KeyLen)
@ -36,29 +36,29 @@ func HashPassword(password string) (string, error) {
func VerifyPassword(password, hash string) (bool, error) { func VerifyPassword(password, hash string) (bool, error) {
parts := strings.Split(hash, "$") parts := strings.Split(hash, "$")
if len(parts) != 6 { if len(parts) != 6 {
return false, core.E("crypt.VerifyPassword", "invalid hash format", nil) return false, coreerr.E("crypt.VerifyPassword", "invalid hash format", nil)
} }
var version int var version int
if _, err := fmt.Sscanf(parts[2], "v=%d", &version); err != nil { if _, err := fmt.Sscanf(parts[2], "v=%d", &version); err != nil {
return false, core.E("crypt.VerifyPassword", "failed to parse version", err) return false, coreerr.E("crypt.VerifyPassword", "failed to parse version", err)
} }
var memory uint32 var memory uint32
var time uint32 var time uint32
var parallelism uint8 var parallelism uint8
if _, err := fmt.Sscanf(parts[3], "m=%d,t=%d,p=%d", &memory, &time, &parallelism); err != nil { if _, err := fmt.Sscanf(parts[3], "m=%d,t=%d,p=%d", &memory, &time, &parallelism); err != nil {
return false, core.E("crypt.VerifyPassword", "failed to parse parameters", err) return false, coreerr.E("crypt.VerifyPassword", "failed to parse parameters", err)
} }
salt, err := base64.RawStdEncoding.DecodeString(parts[4]) salt, err := base64.RawStdEncoding.DecodeString(parts[4])
if err != nil { if err != nil {
return false, core.E("crypt.VerifyPassword", "failed to decode salt", err) return false, coreerr.E("crypt.VerifyPassword", "failed to decode salt", err)
} }
expectedHash, err := base64.RawStdEncoding.DecodeString(parts[5]) expectedHash, err := base64.RawStdEncoding.DecodeString(parts[5])
if err != nil { if err != nil {
return false, core.E("crypt.VerifyPassword", "failed to decode hash", err) return false, coreerr.E("crypt.VerifyPassword", "failed to decode hash", err)
} }
computedHash := argon2.IDKey([]byte(password), salt, time, memory, parallelism, uint32(len(expectedHash))) computedHash := argon2.IDKey([]byte(password), salt, time, memory, parallelism, uint32(len(expectedHash)))
@ -71,7 +71,7 @@ func VerifyPassword(password, hash string) (bool, error) {
func HashBcrypt(password string, cost int) (string, error) { func HashBcrypt(password string, cost int) (string, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), cost) hash, err := bcrypt.GenerateFromPassword([]byte(password), cost)
if err != nil { if err != nil {
return "", core.E("crypt.HashBcrypt", "failed to hash password", err) return "", coreerr.E("crypt.HashBcrypt", "failed to hash password", err)
} }
return string(hash), nil return string(hash), nil
} }
@ -83,7 +83,7 @@ func VerifyBcrypt(password, hash string) (bool, error) {
return false, nil return false, nil
} }
if err != nil { if err != nil {
return false, core.E("crypt.VerifyBcrypt", "failed to verify password", err) return false, coreerr.E("crypt.VerifyBcrypt", "failed to verify password", err)
} }
return true, nil return true, nil
} }

View file

@ -7,7 +7,7 @@ import (
"crypto/sha256" "crypto/sha256"
"io" "io"
core "forge.lthn.ai/core/go-log" coreerr "forge.lthn.ai/core/go-log"
"golang.org/x/crypto/argon2" "golang.org/x/crypto/argon2"
"golang.org/x/crypto/hkdf" "golang.org/x/crypto/hkdf"
"golang.org/x/crypto/scrypt" "golang.org/x/crypto/scrypt"
@ -33,7 +33,7 @@ func DeriveKey(passphrase, salt []byte, keyLen uint32) []byte {
func DeriveKeyScrypt(passphrase, salt []byte, keyLen int) ([]byte, error) { func DeriveKeyScrypt(passphrase, salt []byte, keyLen int) ([]byte, error) {
key, err := scrypt.Key(passphrase, salt, 32768, 8, 1, keyLen) key, err := scrypt.Key(passphrase, salt, 32768, 8, 1, keyLen)
if err != nil { if err != nil {
return nil, core.E("crypt.DeriveKeyScrypt", "failed to derive key", err) return nil, coreerr.E("crypt.DeriveKeyScrypt", "failed to derive key", err)
} }
return key, nil return key, nil
} }
@ -45,7 +45,7 @@ func HKDF(secret, salt, info []byte, keyLen int) ([]byte, error) {
reader := hkdf.New(sha256.New, secret, salt, info) reader := hkdf.New(sha256.New, secret, salt, info)
key := make([]byte, keyLen) key := make([]byte, keyLen)
if _, err := io.ReadFull(reader, key); err != nil { if _, err := io.ReadFull(reader, key); err != nil {
return nil, core.E("crypt.HKDF", "failed to derive key", err) return nil, coreerr.E("crypt.HKDF", "failed to derive key", err)
} }
return key, nil return key, nil
} }
@ -54,7 +54,7 @@ func HKDF(secret, salt, info []byte, keyLen int) ([]byte, error) {
func generateSalt(length int) ([]byte, error) { func generateSalt(length int) ([]byte, error) {
salt := make([]byte, length) salt := make([]byte, length)
if _, err := rand.Read(salt); err != nil { if _, err := rand.Read(salt); err != nil {
return nil, core.E("crypt.generateSalt", "failed to generate random salt", err) return nil, coreerr.E("crypt.generateSalt", "failed to generate random salt", err)
} }
return salt, nil return salt, nil
} }

View file

@ -10,7 +10,7 @@ import (
"github.com/ProtonMail/go-crypto/openpgp/armor" "github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/ProtonMail/go-crypto/openpgp/packet" "github.com/ProtonMail/go-crypto/openpgp/packet"
core "forge.lthn.ai/core/go-log" coreerr "forge.lthn.ai/core/go-log"
framework "forge.lthn.ai/core/go/pkg/core" framework "forge.lthn.ai/core/go/pkg/core"
) )
@ -36,19 +36,19 @@ func (s *Service) CreateKeyPair(name, passphrase string) (string, error) {
entity, err := openpgp.NewEntity(name, "Workspace Key", "", config) entity, err := openpgp.NewEntity(name, "Workspace Key", "", config)
if err != nil { if err != nil {
return "", core.E("openpgp.CreateKeyPair", "failed to create entity", err) return "", coreerr.E("openpgp.CreateKeyPair", "failed to create entity", err)
} }
// Encrypt private key if passphrase is provided // Encrypt private key if passphrase is provided
if passphrase != "" { if passphrase != "" {
err = entity.PrivateKey.Encrypt([]byte(passphrase)) err = entity.PrivateKey.Encrypt([]byte(passphrase))
if err != nil { if err != nil {
return "", core.E("openpgp.CreateKeyPair", "failed to encrypt private key", err) return "", coreerr.E("openpgp.CreateKeyPair", "failed to encrypt private key", err)
} }
for _, subkey := range entity.Subkeys { for _, subkey := range entity.Subkeys {
err = subkey.PrivateKey.Encrypt([]byte(passphrase)) err = subkey.PrivateKey.Encrypt([]byte(passphrase))
if err != nil { if err != nil {
return "", core.E("openpgp.CreateKeyPair", "failed to encrypt subkey", err) return "", coreerr.E("openpgp.CreateKeyPair", "failed to encrypt subkey", err)
} }
} }
} }
@ -56,14 +56,14 @@ func (s *Service) CreateKeyPair(name, passphrase string) (string, error) {
var buf bytes.Buffer var buf bytes.Buffer
w, err := armor.Encode(&buf, openpgp.PrivateKeyType, nil) w, err := armor.Encode(&buf, openpgp.PrivateKeyType, nil)
if err != nil { if err != nil {
return "", core.E("openpgp.CreateKeyPair", "failed to create armor encoder", err) return "", coreerr.E("openpgp.CreateKeyPair", "failed to create armor encoder", err)
} }
// Manual serialization to avoid panic from re-signing encrypted keys // Manual serialization to avoid panic from re-signing encrypted keys
err = s.serializeEntity(w, entity) err = s.serializeEntity(w, entity)
if err != nil { if err != nil {
w.Close() w.Close()
return "", core.E("openpgp.CreateKeyPair", "failed to serialize private key", err) return "", coreerr.E("openpgp.CreateKeyPair", "failed to serialize private key", err)
} }
w.Close() w.Close()
@ -104,13 +104,13 @@ func (s *Service) serializeEntity(w goio.Writer, e *openpgp.Entity) error {
func (s *Service) EncryptPGP(writer goio.Writer, recipientPath, data string, opts ...any) (string, error) { func (s *Service) EncryptPGP(writer goio.Writer, recipientPath, data string, opts ...any) (string, error) {
entityList, err := openpgp.ReadArmoredKeyRing(strings.NewReader(recipientPath)) entityList, err := openpgp.ReadArmoredKeyRing(strings.NewReader(recipientPath))
if err != nil { if err != nil {
return "", core.E("openpgp.EncryptPGP", "failed to read recipient key", err) return "", coreerr.E("openpgp.EncryptPGP", "failed to read recipient key", err)
} }
var armoredBuf bytes.Buffer var armoredBuf bytes.Buffer
armoredWriter, err := armor.Encode(&armoredBuf, "PGP MESSAGE", nil) armoredWriter, err := armor.Encode(&armoredBuf, "PGP MESSAGE", nil)
if err != nil { if err != nil {
return "", core.E("openpgp.EncryptPGP", "failed to create armor encoder", err) return "", coreerr.E("openpgp.EncryptPGP", "failed to create armor encoder", err)
} }
// MultiWriter to write to both the provided writer and our armored buffer // MultiWriter to write to both the provided writer and our armored buffer
@ -119,14 +119,14 @@ func (s *Service) EncryptPGP(writer goio.Writer, recipientPath, data string, opt
w, err := openpgp.Encrypt(mw, entityList, nil, nil, nil) w, err := openpgp.Encrypt(mw, entityList, nil, nil, nil)
if err != nil { if err != nil {
armoredWriter.Close() armoredWriter.Close()
return "", core.E("openpgp.EncryptPGP", "failed to start encryption", err) return "", coreerr.E("openpgp.EncryptPGP", "failed to start encryption", err)
} }
_, err = goio.WriteString(w, data) _, err = goio.WriteString(w, data)
if err != nil { if err != nil {
w.Close() w.Close()
armoredWriter.Close() armoredWriter.Close()
return "", core.E("openpgp.EncryptPGP", "failed to write data", err) return "", coreerr.E("openpgp.EncryptPGP", "failed to write data", err)
} }
w.Close() w.Close()
@ -139,14 +139,14 @@ func (s *Service) EncryptPGP(writer goio.Writer, recipientPath, data string, opt
func (s *Service) DecryptPGP(privateKey, message, passphrase string, opts ...any) (string, error) { func (s *Service) DecryptPGP(privateKey, message, passphrase string, opts ...any) (string, error) {
entityList, err := openpgp.ReadArmoredKeyRing(strings.NewReader(privateKey)) entityList, err := openpgp.ReadArmoredKeyRing(strings.NewReader(privateKey))
if err != nil { if err != nil {
return "", core.E("openpgp.DecryptPGP", "failed to read private key", err) return "", coreerr.E("openpgp.DecryptPGP", "failed to read private key", err)
} }
entity := entityList[0] entity := entityList[0]
if entity.PrivateKey.Encrypted { if entity.PrivateKey.Encrypted {
err = entity.PrivateKey.Decrypt([]byte(passphrase)) err = entity.PrivateKey.Decrypt([]byte(passphrase))
if err != nil { if err != nil {
return "", core.E("openpgp.DecryptPGP", "failed to decrypt private key", err) return "", coreerr.E("openpgp.DecryptPGP", "failed to decrypt private key", err)
} }
for _, subkey := range entity.Subkeys { for _, subkey := range entity.Subkeys {
_ = subkey.PrivateKey.Decrypt([]byte(passphrase)) _ = subkey.PrivateKey.Decrypt([]byte(passphrase))
@ -156,18 +156,18 @@ func (s *Service) DecryptPGP(privateKey, message, passphrase string, opts ...any
// Decrypt armored message // Decrypt armored message
block, err := armor.Decode(strings.NewReader(message)) block, err := armor.Decode(strings.NewReader(message))
if err != nil { if err != nil {
return "", core.E("openpgp.DecryptPGP", "failed to decode armored message", err) return "", coreerr.E("openpgp.DecryptPGP", "failed to decode armored message", err)
} }
md, err := openpgp.ReadMessage(block.Body, entityList, nil, nil) md, err := openpgp.ReadMessage(block.Body, entityList, nil, nil)
if err != nil { if err != nil {
return "", core.E("openpgp.DecryptPGP", "failed to read message", err) return "", coreerr.E("openpgp.DecryptPGP", "failed to read message", err)
} }
var buf bytes.Buffer var buf bytes.Buffer
_, err = goio.Copy(&buf, md.UnverifiedBody) _, err = goio.Copy(&buf, md.UnverifiedBody)
if err != nil { if err != nil {
return "", core.E("openpgp.DecryptPGP", "failed to read decrypted body", err) return "", coreerr.E("openpgp.DecryptPGP", "failed to read decrypted body", err)
} }
return buf.String(), nil return buf.String(), nil

View file

@ -5,7 +5,7 @@ import (
"crypto/cipher" "crypto/cipher"
"crypto/rand" "crypto/rand"
core "forge.lthn.ai/core/go-log" coreerr "forge.lthn.ai/core/go-log"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
) )
@ -15,12 +15,12 @@ import (
func ChaCha20Encrypt(plaintext, key []byte) ([]byte, error) { func ChaCha20Encrypt(plaintext, key []byte) ([]byte, error) {
aead, err := chacha20poly1305.NewX(key) aead, err := chacha20poly1305.NewX(key)
if err != nil { if err != nil {
return nil, core.E("crypt.ChaCha20Encrypt", "failed to create cipher", err) return nil, coreerr.E("crypt.ChaCha20Encrypt", "failed to create cipher", err)
} }
nonce := make([]byte, aead.NonceSize()) nonce := make([]byte, aead.NonceSize())
if _, err := rand.Read(nonce); err != nil { if _, err := rand.Read(nonce); err != nil {
return nil, core.E("crypt.ChaCha20Encrypt", "failed to generate nonce", err) return nil, coreerr.E("crypt.ChaCha20Encrypt", "failed to generate nonce", err)
} }
ciphertext := aead.Seal(nonce, nonce, plaintext, nil) ciphertext := aead.Seal(nonce, nonce, plaintext, nil)
@ -32,18 +32,18 @@ func ChaCha20Encrypt(plaintext, key []byte) ([]byte, error) {
func ChaCha20Decrypt(ciphertext, key []byte) ([]byte, error) { func ChaCha20Decrypt(ciphertext, key []byte) ([]byte, error) {
aead, err := chacha20poly1305.NewX(key) aead, err := chacha20poly1305.NewX(key)
if err != nil { if err != nil {
return nil, core.E("crypt.ChaCha20Decrypt", "failed to create cipher", err) return nil, coreerr.E("crypt.ChaCha20Decrypt", "failed to create cipher", err)
} }
nonceSize := aead.NonceSize() nonceSize := aead.NonceSize()
if len(ciphertext) < nonceSize { if len(ciphertext) < nonceSize {
return nil, core.E("crypt.ChaCha20Decrypt", "ciphertext too short", nil) return nil, coreerr.E("crypt.ChaCha20Decrypt", "ciphertext too short", nil)
} }
nonce, encrypted := ciphertext[:nonceSize], ciphertext[nonceSize:] nonce, encrypted := ciphertext[:nonceSize], ciphertext[nonceSize:]
plaintext, err := aead.Open(nil, nonce, encrypted, nil) plaintext, err := aead.Open(nil, nonce, encrypted, nil)
if err != nil { if err != nil {
return nil, core.E("crypt.ChaCha20Decrypt", "failed to decrypt", err) return nil, coreerr.E("crypt.ChaCha20Decrypt", "failed to decrypt", err)
} }
return plaintext, nil return plaintext, nil
@ -55,17 +55,17 @@ func ChaCha20Decrypt(ciphertext, key []byte) ([]byte, error) {
func AESGCMEncrypt(plaintext, key []byte) ([]byte, error) { func AESGCMEncrypt(plaintext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, core.E("crypt.AESGCMEncrypt", "failed to create cipher", err) return nil, coreerr.E("crypt.AESGCMEncrypt", "failed to create cipher", err)
} }
aead, err := cipher.NewGCM(block) aead, err := cipher.NewGCM(block)
if err != nil { if err != nil {
return nil, core.E("crypt.AESGCMEncrypt", "failed to create GCM", err) return nil, coreerr.E("crypt.AESGCMEncrypt", "failed to create GCM", err)
} }
nonce := make([]byte, aead.NonceSize()) nonce := make([]byte, aead.NonceSize())
if _, err := rand.Read(nonce); err != nil { if _, err := rand.Read(nonce); err != nil {
return nil, core.E("crypt.AESGCMEncrypt", "failed to generate nonce", err) return nil, coreerr.E("crypt.AESGCMEncrypt", "failed to generate nonce", err)
} }
ciphertext := aead.Seal(nonce, nonce, plaintext, nil) ciphertext := aead.Seal(nonce, nonce, plaintext, nil)
@ -77,23 +77,23 @@ func AESGCMEncrypt(plaintext, key []byte) ([]byte, error) {
func AESGCMDecrypt(ciphertext, key []byte) ([]byte, error) { func AESGCMDecrypt(ciphertext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, core.E("crypt.AESGCMDecrypt", "failed to create cipher", err) return nil, coreerr.E("crypt.AESGCMDecrypt", "failed to create cipher", err)
} }
aead, err := cipher.NewGCM(block) aead, err := cipher.NewGCM(block)
if err != nil { if err != nil {
return nil, core.E("crypt.AESGCMDecrypt", "failed to create GCM", err) return nil, coreerr.E("crypt.AESGCMDecrypt", "failed to create GCM", err)
} }
nonceSize := aead.NonceSize() nonceSize := aead.NonceSize()
if len(ciphertext) < nonceSize { if len(ciphertext) < nonceSize {
return nil, core.E("crypt.AESGCMDecrypt", "ciphertext too short", nil) return nil, coreerr.E("crypt.AESGCMDecrypt", "ciphertext too short", nil)
} }
nonce, encrypted := ciphertext[:nonceSize], ciphertext[nonceSize:] nonce, encrypted := ciphertext[:nonceSize], ciphertext[nonceSize:]
plaintext, err := aead.Open(nil, nonce, encrypted, nil) plaintext, err := aead.Open(nil, nonce, encrypted, nil)
if err != nil { if err != nil {
return nil, core.E("crypt.AESGCMDecrypt", "failed to decrypt", err) return nil, coreerr.E("crypt.AESGCMDecrypt", "failed to decrypt", err)
} }
return plaintext, nil return plaintext, nil