/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-// All-Or-Nothing-Transform, based on OAEP.
+// Package aont stands for All-Or-Nothing-Transform, based on OAEP.
//
// This package implements OAEP (Optimal Asymmetric Encryption Padding)
// (http://cseweb.ucsd.edu/~mihir/papers/oaep.html)
// package PKG:
//
// PKG = P1 || P2
-// P1 = Salsa20(key=r, nonce=0x00, 0x00) XOR (M || BLAKE2b(r || M))
+// P1 = ChaCha20(key=r, nonce=0x00, 0x00) XOR (M || BLAKE2b(r || M))
// P2 = BLAKE2b(P1) XOR r
package aont
import (
"crypto/subtle"
- "errors"
- "github.com/dchest/blake2b"
- "golang.org/x/crypto/salsa20"
+ "chacha20"
+ "github.com/pkg/errors"
+ "golang.org/x/crypto/blake2b"
)
const (
+ // HSize size of generated hash output in terms of OAEP
HSize = 32
+ // RSize size of generated random output in terms of OAEP
RSize = 16
+
+ wrapBlake2bNew256 = "blake2b.New256"
+ wrapHashWrite = "hash.Write"
)
var (
- dummyNonce []byte = make([]byte, 8)
+ dummyNonce = new([16]byte)
)
// Encode the data, produce AONT package. Data size will be larger than
func Encode(r *[RSize]byte, in []byte) ([]byte, error) {
out := make([]byte, len(in)+HSize+RSize)
copy(out, in)
- h := blake2b.New256()
- h.Write(r[:])
- h.Write(in)
+ h, err := blake2b.New256(nil)
+ if err != nil {
+ return nil, errors.Wrap(err, wrapBlake2bNew256)
+ }
+ if _, err = h.Write(r[:]); err != nil {
+ return nil, errors.Wrap(err, wrapHashWrite)
+ }
+ if _, err = h.Write(in); err != nil {
+ return nil, errors.Wrap(err, wrapHashWrite)
+ }
copy(out[len(in):], h.Sum(nil))
- salsaKey := new([32]byte)
- copy(salsaKey[:], r[:])
- salsa20.XORKeyStream(out, out, dummyNonce, salsaKey)
+ chachaKey := new([32]byte)
+ copy(chachaKey[:], r[:])
+ chacha20.XORKeyStream(out, out, dummyNonce, chachaKey)
h.Reset()
- h.Write(out[:len(in)+32])
+ if _, err = h.Write(out[:len(in)+32]); err != nil {
+ return nil, errors.Wrap(err, wrapHashWrite)
+ }
for i, b := range h.Sum(nil)[:RSize] {
out[len(in)+32+i] = b ^ r[i]
}
if len(in) < HSize+RSize {
return nil, errors.New("Too small input buffer")
}
- h := blake2b.New256()
- h.Write(in[:len(in)-RSize])
- salsaKey := new([32]byte)
+ h, err := blake2b.New256(nil)
+ if err != nil {
+ return nil, errors.Wrap(err, wrapBlake2bNew256)
+ }
+ if _, err = h.Write(in[:len(in)-RSize]); err != nil {
+ return nil, errors.Wrap(err, wrapHashWrite)
+ }
+ chachaKey := new([32]byte)
for i, b := range h.Sum(nil)[:RSize] {
- salsaKey[i] = b ^ in[len(in)-RSize+i]
+ chachaKey[i] = b ^ in[len(in)-RSize+i]
}
h.Reset()
- h.Write(salsaKey[:RSize])
+ if _, err = h.Write(chachaKey[:RSize]); err != nil {
+ return nil, errors.Wrap(err, wrapHashWrite)
+ }
out := make([]byte, len(in)-RSize)
- salsa20.XORKeyStream(out, in[:len(in)-RSize], dummyNonce, salsaKey)
- h.Write(out[:len(out)-HSize])
+ chacha20.XORKeyStream(out, in[:len(in)-RSize], dummyNonce, chachaKey)
+ if _, err = h.Write(out[:len(out)-HSize]); err != nil {
+ return nil, errors.Wrap(err, wrapHashWrite)
+ }
if subtle.ConstantTimeCompare(h.Sum(nil), out[len(out)-HSize:]) != 1 {
return nil, errors.New("Invalid checksum")
}