1
0
mirror of https://github.com/taigrr/arc synced 2025-01-18 04:33:13 -08:00
2016-05-24 21:26:50 +09:00

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]
}