]> Cypherpunks.ru repositories - nncp.git/blobdiff - src/cypherpunks.ru/nncp/eblob.go
Forbid any later GNU GPL versions autousage
[nncp.git] / src / cypherpunks.ru / nncp / eblob.go
index cb241ab391bc2c862e1168667b30c5808e1d4a1c..36b9d1f3c84fb1f0f3238ea9daa21f5e5d527520 100644 (file)
@@ -1,11 +1,10 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2019 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
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, version 3 of the License.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,17 +19,13 @@ package nncp
 
 import (
        "bytes"
-       "crypto/cipher"
        "crypto/rand"
-       "crypto/subtle"
-       "errors"
-       "io"
+       "hash"
 
        "cypherpunks.ru/balloon"
        "github.com/davecgh/go-xdr/xdr2"
        "golang.org/x/crypto/blake2b"
-       "golang.org/x/crypto/hkdf"
-       "golang.org/x/crypto/twofish"
+       "golang.org/x/crypto/chacha20poly1305"
 )
 
 const (
@@ -40,7 +35,7 @@ const (
 )
 
 var (
-       MagicNNCPBv1 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'B', 0, 0, 1}
+       MagicNNCPBv3 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'B', 0, 0, 3}
 )
 
 type EBlob struct {
@@ -50,7 +45,14 @@ type EBlob struct {
        PCost uint32
        Salt  *[32]byte
        Blob  []byte
-       MAC   *[blake2b.Size256]byte
+}
+
+func blake256() hash.Hash {
+       h, err := blake2b.New256(nil)
+       if err != nil {
+               panic(err)
+       }
+       return h
 }
 
 // Create an encrypted blob. sCost -- memory space requirements, number
@@ -62,47 +64,31 @@ func NewEBlob(sCost, tCost, pCost int, password, data []byte) ([]byte, error) {
        if _, err = rand.Read(salt[:]); err != nil {
                return nil, err
        }
-       key := balloon.H(blake256, password, salt[:], sCost, tCost, pCost)
-       kdf := hkdf.New(blake256, key, nil, MagicNNCPBv1[:])
-       keyEnc := make([]byte, 32)
-       if _, err = io.ReadFull(kdf, keyEnc); err != nil {
-               return nil, err
-       }
-       keyAuth := make([]byte, 64)
-       if _, err = io.ReadFull(kdf, keyAuth); err != nil {
-               return nil, err
-       }
-       ciph, err := twofish.NewCipher(keyEnc)
-       if err != nil {
-               return nil, err
-       }
-       ctr := cipher.NewCTR(ciph, make([]byte, twofish.BlockSize))
-       mac, err := blake2b.New256(keyAuth)
-       if err != nil {
-               return nil, err
-       }
-       var blob bytes.Buffer
-       mw := io.MultiWriter(&blob, mac)
-       ae := &cipher.StreamWriter{S: ctr, W: mw}
-       if _, err = ae.Write(data); err != nil {
-               return nil, err
-       }
-       macTag := new([blake2b.Size256]byte)
-       mac.Sum(macTag[:0])
        eblob := EBlob{
-               Magic: MagicNNCPBv1,
+               Magic: MagicNNCPBv3,
                SCost: uint32(sCost),
                TCost: uint32(tCost),
                PCost: uint32(pCost),
                Salt:  salt,
-               Blob:  blob.Bytes(),
-               MAC:   macTag,
+               Blob:  nil,
+       }
+       var eblobBuf bytes.Buffer
+       if _, err = xdr.Marshal(&eblobBuf, &eblob); err != nil {
+               return nil, err
+       }
+       key := balloon.H(blake256, password, salt[:], sCost, tCost, pCost)
+       aead, err := chacha20poly1305.New(key)
+       if err != nil {
+               return nil, err
        }
-       var eblobRaw bytes.Buffer
-       if _, err = xdr.Marshal(&eblobRaw, &eblob); err != nil {
+       buf := make([]byte, 0, len(data)+aead.Overhead())
+       buf = aead.Seal(buf, make([]byte, aead.NonceSize()), data, eblobBuf.Bytes())
+       eblob.Blob = buf
+       eblobBuf.Reset()
+       if _, err = xdr.Marshal(&eblobBuf, &eblob); err != nil {
                return nil, err
        }
-       return eblobRaw.Bytes(), nil
+       return eblobBuf.Bytes(), nil
 }
 
 func DeEBlob(eblobRaw, password []byte) ([]byte, error) {
@@ -111,7 +97,7 @@ func DeEBlob(eblobRaw, password []byte) ([]byte, error) {
        if _, err = xdr.Unmarshal(bytes.NewReader(eblobRaw), &eblob); err != nil {
                return nil, err
        }
-       if eblob.Magic != MagicNNCPBv1 {
+       if eblob.Magic != MagicNNCPBv3 {
                return nil, BadMagic
        }
        key := balloon.H(
@@ -122,32 +108,25 @@ func DeEBlob(eblobRaw, password []byte) ([]byte, error) {
                int(eblob.TCost),
                int(eblob.PCost),
        )
-       kdf := hkdf.New(blake256, key, nil, MagicNNCPBv1[:])
-       keyEnc := make([]byte, 32)
-       if _, err = io.ReadFull(kdf, keyEnc); err != nil {
-               return nil, err
-       }
-       keyAuth := make([]byte, 64)
-       if _, err = io.ReadFull(kdf, keyAuth); err != nil {
-               return nil, err
-       }
-       ciph, err := twofish.NewCipher(keyEnc)
+       aead, err := chacha20poly1305.New(key)
        if err != nil {
                return nil, err
        }
-       ctr := cipher.NewCTR(ciph, make([]byte, twofish.BlockSize))
-       mac, err := blake2b.New256(keyAuth)
-       if err != nil {
+
+       ciphertext := eblob.Blob
+       eblob.Blob = nil
+       var eblobBuf bytes.Buffer
+       if _, err = xdr.Marshal(&eblobBuf, &eblob); err != nil {
                return nil, err
        }
-       var blob bytes.Buffer
-       tr := io.TeeReader(bytes.NewReader(eblob.Blob), mac)
-       ae := &cipher.StreamReader{S: ctr, R: tr}
-       if _, err = io.Copy(&blob, ae); err != nil {
+       data, err := aead.Open(
+               ciphertext[:0],
+               make([]byte, aead.NonceSize()),
+               ciphertext,
+               eblobBuf.Bytes(),
+       )
+       if err != nil {
                return nil, err
        }
-       if subtle.ConstantTimeCompare(mac.Sum(nil), eblob.MAC[:]) != 1 {
-               return nil, errors.New("Unauthenticated blob")
-       }
-       return blob.Bytes(), nil
+       return data, nil
 }