go-crypt/crypt/chachapoly/chachapoly.go
2026-03-29 15:26:33 +00:00

54 lines
1.3 KiB
Go

package chachapoly
import (
"crypto/rand"
"fmt"
"io"
coreerr "dappco.re/go/core/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
}