import (
"bytes"
- "crypto/cipher"
"crypto/hkdf"
"crypto/subtle"
"errors"
"hash"
"io"
+ "github.com/aead/chacha20"
"go.cypherpunks.su/keks"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/chacha20poly1305"
+ "golang.org/x/crypto/poly1305"
)
const (
- ChunkLen = 128 * 1024
- CommitmentLen = 32
- CEKLen = blake2b.Size
- DEMAlgo = "xchapoly-krkc"
+ ChunkLen = 128 * 1024
+ CommitmentLen = 32
+ CEKLen = blake2b.Size
+ DEMAlgo = "xchapoly-krkc"
+ Poly1305KeyLen = 32
)
type keymat struct {
key []byte
+ mac [Poly1305KeyLen]byte
iv []byte
}
go func() {
ck := cek
var key []byte
+ var mac []byte
var iv []byte
var errHKDF error
for {
- key, errHKDF = hkdf.Expand(
- blake2bHash, ck, "cm/encrypted/xchapoly-krkc/key",
- chacha20poly1305.KeySize)
+ ck, errHKDF = hkdf.Extract(blake2bHash, nil, ck)
if errHKDF != nil {
panic(errHKDF)
}
- iv, errHKDF = hkdf.Expand(
- blake2bHash, ck, "cm/encrypted/xchapoly-krkc/iv",
- chacha20poly1305.NonceSizeX)
+ ck, errHKDF = hkdf.Expand(
+ blake2bHash, ck, "cm/encrypted/xchapoly-krkc/kr", CEKLen)
if errHKDF != nil {
panic(errHKDF)
}
- keymats <- keymat{key: key, iv: iv}
- ck, errHKDF = hkdf.Extract(blake2bHash, nil, ck)
+ key, errHKDF = hkdf.Expand(
+ blake2bHash, ck, "cm/encrypted/xchapoly-krkc/key",
+ chacha20poly1305.KeySize)
if errHKDF != nil {
panic(errHKDF)
}
- ck, errHKDF = hkdf.Expand(
- blake2bHash, ck, "cm/encrypted/xchapoly-krkc/kr", CEKLen)
+ mac, errHKDF = hkdf.Expand(
+ blake2bHash, ck, "cm/encrypted/xchapoly-krkc/mac",
+ Poly1305KeyLen)
if errHKDF != nil {
panic(errHKDF)
}
+ iv, errHKDF = hkdf.Expand(
+ blake2bHash, ck, "cm/encrypted/xchapoly-krkc/iv",
+ chacha20poly1305.NonceSizeX)
+ if errHKDF != nil {
+ panic(errHKDF)
+ }
+ k := keymat{key: key, iv: iv}
+ copy(k.mac[:], mac)
+ keymats <- k
}
}()
- blobChunkLen := ChunkLen + chacha20poly1305.Overhead + CommitmentLen
+ blobChunkLen := ChunkLen + +CommitmentLen
var blobDecoder *keks.BlobDecoder
if seal {
if blob {
}
ready <- &j
var errJob error
- var ciph cipher.AEAD
var com hash.Hash
- var tag []byte
+ var tag [16]byte
ourCom := make([]byte, CommitmentLen)
for {
<-j.bufReady
- ciph, errJob = chacha20poly1305.NewX(j.keymat.key)
- if errJob != nil {
- panic(errJob)
- }
com, errJob = blake2b.New(CommitmentLen, nil)
if errJob != nil {
panic(errJob)
}
if seal {
- ciph.Seal(
- j.buf[:0],
+ chacha20.XORKeyStream(
+ j.buf[:len(j.buf)-CommitmentLen],
+ j.buf[:len(j.buf)-CommitmentLen],
j.keymat.iv,
- j.buf[:len(j.buf)-chacha20poly1305.Overhead-CommitmentLen],
- nil,
+ j.keymat.key,
+ )
+ poly1305.Sum(
+ &tag,
+ j.buf[:len(j.buf)-CommitmentLen],
+ &j.keymat.mac,
)
- tag = j.buf[len(j.buf)-chacha20poly1305.Overhead-CommitmentLen:]
- tag = tag[:chacha20poly1305.Overhead]
com.Write(j.keymat.key)
com.Write(j.keymat.iv)
- com.Write(tag)
+ com.Write(j.keymat.mac[:])
+ com.Write(tag[:])
com.Sum(j.buf[:len(j.buf)-CommitmentLen])
} else {
- tag = j.buf[len(j.buf)-chacha20poly1305.Overhead-CommitmentLen:]
- tag = tag[:chacha20poly1305.Overhead]
+ poly1305.Sum(
+ &tag,
+ j.buf[:len(j.buf)-CommitmentLen],
+ &j.keymat.mac,
+ )
com.Write(j.keymat.key)
com.Write(j.keymat.iv)
- com.Write(tag)
+ com.Write(j.keymat.mac[:])
+ com.Write(tag[:])
ourCom = com.Sum(ourCom[:0])
if subtle.ConstantTimeCompare(
ourCom,
j.buf[len(j.buf)-CommitmentLen:],
) == 1 {
- j.buf, errJob = ciph.Open(
- j.buf[:0], j.keymat.iv, j.buf[:len(j.buf)-CommitmentLen], nil,
+ chacha20.XORKeyStream(
+ j.buf[:len(j.buf)-CommitmentLen],
+ j.buf[:len(j.buf)-CommitmentLen],
+ j.keymat.iv,
+ j.keymat.key,
)
+ j.buf = j.buf[:len(j.buf)-CommitmentLen]
} else {
errJob = errors.New("commitment differs")
}
errR = nil
eof = true
if seal {
- j.buf = j.buf[:n+chacha20poly1305.Overhead+CommitmentLen]
+ j.buf = j.buf[:n+CommitmentLen]
}
}
if !seal && n == 0 {