mirror of
https://github.com/taigrr/arc
synced 2025-01-18 04:33:13 -08:00
77 lines
1.4 KiB
Go
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
|
|
}
|