]> 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 b25f5ab208dd9269848c42dad5d06a9c2175f1d0..36b9d1f3c84fb1f0f3238ea9daa21f5e5d527520 100644 (file)
@@ -1,11 +1,10 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2018 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
@@ -21,15 +20,12 @@ package nncp
 import (
        "bytes"
        "crypto/rand"
-       "crypto/subtle"
-       "errors"
        "hash"
-       "io"
 
-       "chacha20"
        "cypherpunks.ru/balloon"
        "github.com/davecgh/go-xdr/xdr2"
        "golang.org/x/crypto/blake2b"
+       "golang.org/x/crypto/chacha20poly1305"
 )
 
 const (
@@ -39,7 +35,7 @@ const (
 )
 
 var (
-       MagicNNCPBv2 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'B', 0, 0, 2}
+       MagicNNCPBv3 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'B', 0, 0, 3}
 )
 
 type EBlob struct {
@@ -49,7 +45,6 @@ type EBlob struct {
        PCost uint32
        Salt  *[32]byte
        Blob  []byte
-       MAC   *[blake2b.Size256]byte
 }
 
 func blake256() hash.Hash {
@@ -69,46 +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, err := blake2b.NewXOF(32+64, key)
-       if err != nil {
-               return nil, err
-       }
-       if _, err = kdf.Write(MagicNNCPBv2[:]); err != nil {
-               return nil, err
-       }
-       keyEnc := new([32]byte)
-       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
-       }
-       mac, err := blake2b.New256(keyAuth)
-       if err != nil {
-               return nil, err
-       }
-       chacha20.XORKeyStream(data, data, new([16]byte), keyEnc)
-       if _, err = mac.Write(data); err != nil {
-               return nil, err
-       }
-       macTag := new([blake2b.Size256]byte)
-       mac.Sum(macTag[:0])
        eblob := EBlob{
-               Magic: MagicNNCPBv2,
+               Magic: MagicNNCPBv3,
                SCost: uint32(sCost),
                TCost: uint32(tCost),
                PCost: uint32(pCost),
                Salt:  salt,
-               Blob:  data,
-               MAC:   macTag,
+               Blob:  nil,
        }
-       var eblobRaw bytes.Buffer
-       if _, err = xdr.Marshal(&eblobRaw, &eblob); err != nil {
+       var eblobBuf bytes.Buffer
+       if _, err = xdr.Marshal(&eblobBuf, &eblob); err != nil {
                return nil, err
        }
-       return eblobRaw.Bytes(), nil
+       key := balloon.H(blake256, password, salt[:], sCost, tCost, pCost)
+       aead, err := chacha20poly1305.New(key)
+       if err != nil {
+               return nil, err
+       }
+       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 eblobBuf.Bytes(), nil
 }
 
 func DeEBlob(eblobRaw, password []byte) ([]byte, error) {
@@ -117,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 != MagicNNCPBv2 {
+       if eblob.Magic != MagicNNCPBv3 {
                return nil, BadMagic
        }
        key := balloon.H(
@@ -128,31 +108,25 @@ func DeEBlob(eblobRaw, password []byte) ([]byte, error) {
                int(eblob.TCost),
                int(eblob.PCost),
        )
-       kdf, err := blake2b.NewXOF(32+64, key)
+       aead, err := chacha20poly1305.New(key)
        if err != nil {
                return nil, err
        }
-       if _, err = kdf.Write(MagicNNCPBv2[:]); err != nil {
-               return nil, err
-       }
-       keyEnc := new([32]byte)
-       if _, err = io.ReadFull(kdf, keyEnc[:]); err != nil {
-               return nil, err
-       }
-       keyAuth := make([]byte, 64)
-       if _, err = io.ReadFull(kdf, keyAuth); err != nil {
+
+       ciphertext := eblob.Blob
+       eblob.Blob = nil
+       var eblobBuf bytes.Buffer
+       if _, err = xdr.Marshal(&eblobBuf, &eblob); err != nil {
                return nil, err
        }
-       mac, err := blake2b.New256(keyAuth)
+       data, err := aead.Open(
+               ciphertext[:0],
+               make([]byte, aead.NonceSize()),
+               ciphertext,
+               eblobBuf.Bytes(),
+       )
        if err != nil {
                return nil, err
        }
-       if _, err = mac.Write(eblob.Blob); err != nil {
-               return nil, err
-       }
-       if subtle.ConstantTimeCompare(mac.Sum(nil), eblob.MAC[:]) != 1 {
-               return nil, errors.New("Unauthenticated blob")
-       }
-       chacha20.XORKeyStream(eblob.Blob, eblob.Blob, new([16]byte), keyEnc)
-       return eblob.Blob, nil
+       return data, nil
 }