gocrypt/pkg/crypto/crypto.go
2019-06-25 20:57:03 +02:00

71 lines
1.4 KiB
Go

// Copyright (C) 2019 Marius Schellenberger
package crypto
import (
"crypto/rand"
"errors"
"golang.org/x/crypto/argon2"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/ssh/terminal"
"io"
"os"
)
const (
SaltSize = 16
PrefixSize = SaltSize + chacha20poly1305.NonceSizeX
)
func randomBytes(l int) (b []byte) {
b = make([]byte, l)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
return
}
func kdf(password, salt []byte) []byte {
return argon2.IDKey(password, salt, 1, 64*1024, 4, chacha20poly1305.KeySize)
}
func Password() ([]byte, error) {
return terminal.ReadPassword(int(os.Stdin.Fd()))
}
func Encrypt(pass, src []byte, dst io.Writer) (err error) {
salt := randomBytes(SaltSize)
nonce := randomBytes(chacha20poly1305.NonceSizeX)
aead, err := chacha20poly1305.NewX(kdf(pass, salt))
if err != nil {
return
}
_, err = dst.Write(salt)
if err != nil {
return
}
_, err = dst.Write(nonce)
if err != nil {
return
}
_, err = dst.Write(aead.Seal(nil, nonce, src, nil))
return
}
func Decrypt(pass, src []byte, dst io.Writer) (err error) {
if len(src) <= PrefixSize {
return errors.New("input file corrupted")
}
nonce := src[SaltSize:PrefixSize]
aead, err := chacha20poly1305.NewX(kdf(pass, src[:SaltSize]))
if err != nil {
return
}
dec, err := aead.Open(nil, nonce, src[PrefixSize:], nil)
if err != nil {
return
}
_, err = dst.Write(dec)
return
}