- auth: prevent legacy .lthn fallback when .hash file exists but is unreadable or has unexpected format (security fix in verifyPassword and Login) - chachapoly: wrap raw error returns in Decrypt with coreerr.E() - trust: reject trailing data in LoadPolicies JSON decoder Co-Authored-By: Virgil <virgil@lethean.io>
54 lines
1.3 KiB
Go
54 lines
1.3 KiB
Go
package chachapoly
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"fmt"
|
|
"io"
|
|
|
|
coreerr "forge.lthn.ai/core/go-log"
|
|
|
|
"golang.org/x/crypto/chacha20poly1305"
|
|
)
|
|
|
|
// Encrypt encrypts data using ChaCha20-Poly1305.
|
|
func Encrypt(plaintext []byte, key []byte) ([]byte, error) {
|
|
aead, err := chacha20poly1305.NewX(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(plaintext)+aead.Overhead())
|
|
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return aead.Seal(nonce, nonce, plaintext, nil), nil
|
|
}
|
|
|
|
// Decrypt decrypts data using ChaCha20-Poly1305.
|
|
func Decrypt(ciphertext []byte, key []byte) ([]byte, error) {
|
|
const op = "chachapoly.Decrypt"
|
|
|
|
aead, err := chacha20poly1305.NewX(key)
|
|
if err != nil {
|
|
return nil, coreerr.E(op, "failed to create cipher", err)
|
|
}
|
|
|
|
minLen := aead.NonceSize() + aead.Overhead()
|
|
if len(ciphertext) < minLen {
|
|
return nil, coreerr.E(op, fmt.Sprintf("ciphertext too short: got %d bytes, need at least %d bytes", len(ciphertext), minLen), nil)
|
|
}
|
|
|
|
nonce, ciphertext := ciphertext[:aead.NonceSize()], ciphertext[aead.NonceSize():]
|
|
|
|
decrypted, err := aead.Open(nil, nonce, ciphertext, nil)
|
|
if err != nil {
|
|
return nil, coreerr.E(op, "decryption failed", err)
|
|
}
|
|
|
|
if len(decrypted) == 0 {
|
|
return []byte{}, nil
|
|
}
|
|
|
|
return decrypted, nil
|
|
}
|