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

91 lines
1.8 KiB
Go

// Copyright (C) 2016 - Will Glozer. All rights reserved.
package ecies
import (
"crypto/subtle"
"errors"
"github.com/dchest/blake2b"
"github.com/wg/ecies/xchacha20poly1305"
)
var (
ErrBoxAuthFailed = errors.New("box: message auth failed")
ErrBoxTooSmall = errors.New("box: destination too small")
ErrBoxInvariant = errors.New("box: invariant violation")
)
type Box struct {
key [xchacha20poly1305.KeySize]byte
xchacha20poly1305.XChaCha20Poly1305
}
func NewX25519XChaCha20Poly1305(publicKey, privateKey *[32]byte) (*Box, error) {
var secret [32]byte
if err := X25519(&secret, publicKey, privateKey); err != nil {
return nil, err
}
return newXChaCha20Poly1305Box(secret[:])
}
func NewX448XChaCha20Poly1305(publicKey, privateKey *[56]byte) (*Box, error) {
var secret [56]byte
if err := X448(&secret, publicKey, privateKey); err != nil {
return nil, err
}
return newXChaCha20Poly1305Box(secret[:])
}
func (b *Box) Seal(dst, msg, nonce []byte) error {
if cap(dst) < len(msg)+xchacha20poly1305.TagSize {
return ErrBoxTooSmall
}
if err := b.Init(b.key[:], nonce); err != nil {
return err
}
n := len(msg)
b.Encrypt(dst, msg)
b.Tag(dst[n:n])
return nil
}
func (b *Box) Open(dst, msg, nonce []byte) error {
if cap(dst) < len(msg)-xchacha20poly1305.TagSize {
return ErrBoxTooSmall
}
if err := b.Init(b.key[:], nonce); err != nil {
return err
}
n := len(msg) - xchacha20poly1305.TagSize
msg, tag := msg[:n], msg[n:]
b.Decrypt(dst, msg)
if subtle.ConstantTimeCompare(tag, b.Tag(nil)) != 1 {
return ErrBoxAuthFailed
}
return nil
}
func newXChaCha20Poly1305Box(secret []byte) (*Box, error) {
h, err := blake2b.New(&blake2b.Config{
Size: xchacha20poly1305.KeySize,
})
if err != nil {
return nil, ErrBoxInvariant
}
box := &Box{}
h.Write(secret)
h.Sum(box.key[:0])
return box, nil
}