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

77 lines
1.4 KiB
Go

// Copyright (C) 2016 - Will Glozer. All rights reserved.
package archive
import (
"crypto/rand"
"crypto/subtle"
"io"
"github.com/wg/ecies/xchacha20poly1305"
)
const KeySize = xchacha20poly1305.KeySize
type Archive struct {
xchacha20poly1305.XChaCha20Poly1305
tag [xchacha20poly1305.TagSize]byte
io.Reader
io.Writer
}
func NewArchiveFromReader(r io.Reader, key []byte) (*Archive, error) {
var nonce [xchacha20poly1305.NonceSize]byte
a := &Archive{Reader: r}
if _, err := io.ReadFull(r, a.tag[:]); err != nil {
return nil, err
}
if _, err := io.ReadFull(r, nonce[:]); err != nil {
return nil, err
}
err := a.Init(key, nonce[:])
return a, err
}
func NewArchiveForWriter(w io.Writer, key []byte) (*Archive, error) {
var nonce [xchacha20poly1305.NonceSize]byte
a := &Archive{Writer: w}
if _, err := rand.Read(nonce[:]); err != nil {
return nil, err
}
if err := a.Init(key, nonce[:]); err != nil {
return nil, err
}
if _, err := w.Write(a.tag[:]); err != nil {
return nil, err
}
if _, err := w.Write(nonce[:]); err != nil {
return nil, err
}
return a, nil
}
func (a *Archive) Read(b []byte) (int, error) {
n, err := a.Reader.Read(b)
a.Decrypt(b[:n], b[:n])
return n, err
}
func (a *Archive) Write(b []byte) (int, error) {
a.Encrypt(b, b)
return a.Writer.Write(b)
}
func (a *Archive) Verify() bool {
var tag [xchacha20poly1305.TagSize]byte
a.Tag(tag[:0])
return subtle.ConstantTimeCompare(a.tag[:], tag[:]) == 1
}