starcrypto/symm/chacha20.go

66 lines
1.6 KiB
Go

package symm
import (
"crypto/cipher"
"errors"
"io"
"golang.org/x/crypto/chacha20"
"golang.org/x/crypto/chacha20poly1305"
)
var ErrInvalidChaCha20NonceLength = errors.New("chacha20 nonce length must be 12 or 24 bytes")
func EncryptChaCha20(data, key, nonce []byte) ([]byte, error) {
stream, err := chacha20.NewUnauthenticatedCipher(key, nonce)
if err != nil {
return nil, err
}
out := make([]byte, len(data))
stream.XORKeyStream(out, data)
return out, nil
}
func DecryptChaCha20(src, key, nonce []byte) ([]byte, error) {
return EncryptChaCha20(src, key, nonce)
}
func EncryptChaCha20Stream(dst io.Writer, src io.Reader, key, nonce []byte) error {
stream, err := chacha20.NewUnauthenticatedCipher(key, nonce)
if err != nil {
return err
}
return xorStreamCopy(dst, src, stream)
}
func DecryptChaCha20Stream(dst io.Writer, src io.Reader, key, nonce []byte) error {
return EncryptChaCha20Stream(dst, src, key, nonce)
}
func EncryptChaCha20Poly1305(plain, key, nonce, aad []byte) ([]byte, error) {
aead, err := newChaCha20AEAD(key, nonce)
if err != nil {
return nil, err
}
return aead.Seal(nil, nonce, plain, aad), nil
}
func DecryptChaCha20Poly1305(ciphertext, key, nonce, aad []byte) ([]byte, error) {
aead, err := newChaCha20AEAD(key, nonce)
if err != nil {
return nil, err
}
return aead.Open(nil, nonce, ciphertext, aad)
}
func newChaCha20AEAD(key, nonce []byte) (cipher.AEAD, error) {
switch len(nonce) {
case chacha20poly1305.NonceSize:
return chacha20poly1305.New(key)
case chacha20poly1305.NonceSizeX:
return chacha20poly1305.NewX(key)
default:
return nil, ErrInvalidChaCha20NonceLength
}
}