mirror of
https://github.com/taigrr/arc
synced 2025-01-18 04:33:13 -08:00
107 lines
1.9 KiB
Go
107 lines
1.9 KiB
Go
// Copyright (C) 2016 - Will Glozer. All rights reserved.
|
|
|
|
package ecies
|
|
|
|
import (
|
|
"crypto/cipher"
|
|
"crypto/subtle"
|
|
"errors"
|
|
|
|
"github.com/wg/ecies/chacha20poly1305"
|
|
"github.com/wg/ecies/xchacha20poly1305"
|
|
)
|
|
|
|
var (
|
|
ErrInvalidKeySize = errors.New("cipher: invalid key length")
|
|
ErrAuthFailed = errors.New("cipher: message auth failed")
|
|
)
|
|
|
|
type AEAD struct {
|
|
key []byte
|
|
nonceSize int
|
|
tagSize int
|
|
Cipher
|
|
}
|
|
|
|
func NewXChaCha20Poly1305(key []byte) (cipher.AEAD, error) {
|
|
if len(key) != xchacha20poly1305.KeySize {
|
|
return nil, ErrInvalidKeySize
|
|
}
|
|
|
|
core := &xchacha20poly1305.XChaCha20Poly1305{}
|
|
|
|
return &AEAD{
|
|
key: key,
|
|
nonceSize: xchacha20poly1305.NonceSize,
|
|
tagSize: xchacha20poly1305.TagSize,
|
|
Cipher: core,
|
|
}, nil
|
|
}
|
|
|
|
func NewChaCha20Poly1305(key []byte) (cipher.AEAD, error) {
|
|
if len(key) != chacha20poly1305.KeySize {
|
|
return nil, ErrInvalidKeySize
|
|
}
|
|
|
|
core := &chacha20poly1305.ChaCha20Poly1305{}
|
|
|
|
return &AEAD{
|
|
key: key,
|
|
nonceSize: chacha20poly1305.NonceSize,
|
|
tagSize: chacha20poly1305.TagSize,
|
|
Cipher: core,
|
|
}, nil
|
|
}
|
|
|
|
func (a *AEAD) NonceSize() int {
|
|
return a.nonceSize
|
|
}
|
|
|
|
func (a *AEAD) Overhead() int {
|
|
return a.tagSize
|
|
}
|
|
|
|
func (a *AEAD) Open(dst, nonce, src, aad []byte) ([]byte, error) {
|
|
err := a.Init(a.key, nonce)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
n := len(src) - a.tagSize
|
|
dst, ret := extend(dst, n)
|
|
src, tag := src[:n], src[n:]
|
|
|
|
a.Auth(aad)
|
|
a.Decrypt(dst, src)
|
|
|
|
if subtle.ConstantTimeCompare(tag, a.Tag(nil)) != 1 {
|
|
return nil, ErrAuthFailed
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (a *AEAD) Seal(dst, nonce, src, aad []byte) []byte {
|
|
err := a.Init(a.key, nonce)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
n := len(src) + a.tagSize
|
|
dst, ret := extend(dst, n)
|
|
tag := dst[len(src):]
|
|
|
|
a.Auth(aad)
|
|
a.Encrypt(dst, src)
|
|
a.Tag(tag[:0])
|
|
|
|
return ret
|
|
}
|
|
|
|
func extend(dst []byte, n int) ([]byte, []byte) {
|
|
if len(dst) < n {
|
|
dst = append(dst, make([]byte, n)...)
|
|
}
|
|
return dst, dst[:n]
|
|
}
|