- removed spurious check in decrypt() against blocksize - added additional tests for small sized blocks and inputs smaller than the blocksize. - updated README to capture dependencies (protobuf tools)
This commit is contained in:
parent
bce89dacb0
commit
445c13ca6f
4 changed files with 145 additions and 8 deletions
|
@ -260,7 +260,7 @@ func (e *Encryptor) start(wr io.Writer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypt exactly _one_ block of data
|
// encrypt exactly _one_ block of data
|
||||||
// The nonce for the block is: sha256(salt || chunkLen || block#)
|
// The nonce is constructed from the salt, block# and block-size.
|
||||||
// This protects the output stream from re-ordering attacks and length
|
// This protects the output stream from re-ordering attacks and length
|
||||||
// modification attacks. The encoded length & block number is used as
|
// modification attacks. The encoded length & block number is used as
|
||||||
// additional data in the AEAD construction.
|
// additional data in the AEAD construction.
|
||||||
|
@ -473,7 +473,6 @@ func (d *Decryptor) Decrypt(wr io.Writer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt exactly one chunk of data
|
// Decrypt exactly one chunk of data
|
||||||
|
@ -490,7 +489,6 @@ func (d *Decryptor) decrypt(i uint32) ([]byte, bool, error) {
|
||||||
|
|
||||||
m := binary.BigEndian.Uint32(b[:4])
|
m := binary.BigEndian.Uint32(b[:4])
|
||||||
eof := (m & _EOF) > 0
|
eof := (m & _EOF) > 0
|
||||||
|
|
||||||
m &= (_EOF - 1)
|
m &= (_EOF - 1)
|
||||||
|
|
||||||
// Sanity check - in case of corrupt header
|
// Sanity check - in case of corrupt header
|
||||||
|
@ -504,9 +502,6 @@ func (d *Decryptor) decrypt(i uint32) ([]byte, bool, error) {
|
||||||
}
|
}
|
||||||
return p, eof, nil
|
return p, eof, nil
|
||||||
|
|
||||||
case m < ovh:
|
|
||||||
return nil, false, fmt.Errorf("decrypt: chunksize is too small (%d)", m)
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,57 @@ func TestEncryptSimple(t *testing.T) {
|
||||||
assert(byteEq(b, buf), "decrypt content mismatch")
|
assert(byteEq(b, buf), "decrypt content mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// one sender, one receiver - small blocks
|
||||||
|
func TestEncryptSmallSizes(t *testing.T) {
|
||||||
|
assert := newAsserter(t)
|
||||||
|
|
||||||
|
receiver, err := NewKeypair()
|
||||||
|
assert(err == nil, "receiver keypair gen failed: %s", err)
|
||||||
|
|
||||||
|
var blkSize int = 8
|
||||||
|
var size int = (blkSize * 4)
|
||||||
|
|
||||||
|
// cleartext
|
||||||
|
bigbuf := make([]byte, size)
|
||||||
|
for i := 0; i < len(bigbuf); i++ {
|
||||||
|
bigbuf[i] = byte(i & 0xff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encrypt progressively larger bufs
|
||||||
|
for i := 1; i < len(bigbuf); i++ {
|
||||||
|
buf := bigbuf[:i]
|
||||||
|
|
||||||
|
ee, err := NewEncryptor(nil, uint64(blkSize))
|
||||||
|
assert(err == nil, "encryptor-%d create fail: %s", i, err)
|
||||||
|
|
||||||
|
err = ee.AddRecipient(&receiver.Pub)
|
||||||
|
assert(err == nil, "encryptor-%d: can't add recipient: %s", i, err)
|
||||||
|
|
||||||
|
rd := bytes.NewBuffer(buf)
|
||||||
|
wr := Buffer{}
|
||||||
|
|
||||||
|
err = ee.Encrypt(rd, &wr)
|
||||||
|
assert(err == nil, "encrypt-%d fail: %s", i, err)
|
||||||
|
|
||||||
|
rd = bytes.NewBuffer(wr.Bytes())
|
||||||
|
|
||||||
|
dd, err := NewDecryptor(rd)
|
||||||
|
assert(err == nil, "decryptor-%d create fail: %s", i, err)
|
||||||
|
|
||||||
|
err = dd.SetPrivateKey(&receiver.Sec, nil)
|
||||||
|
assert(err == nil, "decryptor-%d can't add SK: %s", i, err)
|
||||||
|
|
||||||
|
wr = Buffer{}
|
||||||
|
err = dd.Decrypt(&wr)
|
||||||
|
assert(err == nil, "decrypt-%d fail: %s", i, err)
|
||||||
|
|
||||||
|
b := wr.Bytes()
|
||||||
|
assert(len(b) == len(buf), "decrypt-%d length mismatch: exp %d, saw %d", i, len(buf), len(b))
|
||||||
|
|
||||||
|
assert(byteEq(b, buf), "decrypt-%d content mismatch", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test corrupted header or corrupted input
|
// test corrupted header or corrupted input
|
||||||
func TestEncryptCorrupted(t *testing.T) {
|
func TestEncryptCorrupted(t *testing.T) {
|
||||||
assert := newAsserter(t)
|
assert := newAsserter(t)
|
||||||
|
@ -313,6 +364,93 @@ func TestStreamIO(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test stream write and read with small sizes
|
||||||
|
func TestSmallSizeStreamIO(t *testing.T) {
|
||||||
|
assert := newAsserter(t)
|
||||||
|
|
||||||
|
receiver, err := NewKeypair()
|
||||||
|
assert(err == nil, "receiver keypair gen failed: %s", err)
|
||||||
|
|
||||||
|
var blkSize int = 8
|
||||||
|
var size int = blkSize * 10
|
||||||
|
|
||||||
|
// cleartext
|
||||||
|
bigbuf := make([]byte, size)
|
||||||
|
for i := 0; i < len(bigbuf); i++ {
|
||||||
|
bigbuf[i] = byte(i & 0xff)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i < len(bigbuf); i++ {
|
||||||
|
buf := bigbuf[:i]
|
||||||
|
t.Logf("small-size-stream: size %d, chunksize %d\n", i, blkSize)
|
||||||
|
|
||||||
|
ee, err := NewEncryptor(nil, uint64(blkSize))
|
||||||
|
assert(err == nil, "encryptor create fail: %s", err)
|
||||||
|
|
||||||
|
err = ee.AddRecipient(&receiver.Pub)
|
||||||
|
assert(err == nil, "can't add recipient: %s", err)
|
||||||
|
|
||||||
|
wr := Buffer{}
|
||||||
|
wio, err := ee.NewStreamWriter(&wr)
|
||||||
|
assert(err == nil, "can't start stream writer: %s", err)
|
||||||
|
|
||||||
|
// chunksize for writing to stream
|
||||||
|
csize := blkSize - 1
|
||||||
|
rbuf := buf
|
||||||
|
for len(rbuf) > 0 {
|
||||||
|
m := csize
|
||||||
|
if len(rbuf) < m {
|
||||||
|
m = len(rbuf)
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := wio.Write(rbuf[:m])
|
||||||
|
assert(err == nil, "stream write failed: %s", err)
|
||||||
|
assert(n == m, "stream write mismatch: exp %d, saw %d", m, n)
|
||||||
|
|
||||||
|
rbuf = rbuf[m:]
|
||||||
|
}
|
||||||
|
err = wio.Close()
|
||||||
|
assert(err == nil, "stream close failed: %s", err)
|
||||||
|
|
||||||
|
_, err = wio.Write(buf[:csize])
|
||||||
|
assert(err != nil, "stream write accepted I/O after close: %s", err)
|
||||||
|
|
||||||
|
rd := bytes.NewBuffer(wr.Bytes())
|
||||||
|
|
||||||
|
dd, err := NewDecryptor(rd)
|
||||||
|
assert(err == nil, "decryptor create fail: %s", err)
|
||||||
|
|
||||||
|
err = dd.SetPrivateKey(&receiver.Sec, nil)
|
||||||
|
assert(err == nil, "decryptor can't add SK: %s", err)
|
||||||
|
|
||||||
|
rio, err := dd.NewStreamReader()
|
||||||
|
assert(err == nil, "stream reader failed: %s", err)
|
||||||
|
|
||||||
|
rbuf = make([]byte, csize)
|
||||||
|
wr = Buffer{}
|
||||||
|
n := 0
|
||||||
|
for {
|
||||||
|
m, err := rio.Read(rbuf)
|
||||||
|
assert(err == nil || err == io.EOF, "streamread fail: %s", err)
|
||||||
|
|
||||||
|
if m > 0 {
|
||||||
|
wr.Write(rbuf[:m])
|
||||||
|
n += m
|
||||||
|
}
|
||||||
|
if err == io.EOF || m == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b := wr.Bytes()
|
||||||
|
assert(n == len(b), "streamread: bad buflen; exp %d, saw %d", n, len(b))
|
||||||
|
assert(n == len(buf), "streamread: decrypt len mismatch; exp %d, saw %d", len(buf), n)
|
||||||
|
|
||||||
|
assert(byteEq(b, buf), "decrypt content mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func randint() int {
|
func randint() int {
|
||||||
var b [4]byte
|
var b [4]byte
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,8 @@ func parseSSHPrivateKey(data []byte, getpw func() ([]byte, error)) (*PrivateKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSSHPublicKey(in []byte) (*PublicKey, error) {
|
func parseSSHPublicKey(in []byte) (*PublicKey, error) {
|
||||||
splitter := regexp.MustCompile("[ \\t]+");
|
splitter := regexp.MustCompile("[ \\t]+")
|
||||||
v := splitter.Split(string(in), -1);
|
v := splitter.Split(string(in), -1)
|
||||||
if len(v) != 3 {
|
if len(v) != 3 {
|
||||||
return nil, ErrBadPublicKey
|
return nil, ErrBadPublicKey
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ type encWriter struct {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ io.WriteCloser = &encWriter{}
|
||||||
|
|
||||||
// NewStreamWriter begins stream encryption to an underlying destination writer 'wr'.
|
// NewStreamWriter begins stream encryption to an underlying destination writer 'wr'.
|
||||||
// It returns an io.WriteCloser.
|
// It returns an io.WriteCloser.
|
||||||
func (e *Encryptor) NewStreamWriter(wr io.WriteCloser) (io.WriteCloser, error) {
|
func (e *Encryptor) NewStreamWriter(wr io.WriteCloser) (io.WriteCloser, error) {
|
||||||
|
@ -108,6 +110,8 @@ type encReader struct {
|
||||||
blk uint32
|
blk uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ io.Reader = &encReader{}
|
||||||
|
|
||||||
// NewStreamReader returns an io.Reader to read from the decrypted stream
|
// NewStreamReader returns an io.Reader to read from the decrypted stream
|
||||||
func (d *Decryptor) NewStreamReader() (io.Reader, error) {
|
func (d *Decryptor) NewStreamReader() (io.Reader, error) {
|
||||||
if d.key == nil {
|
if d.key == nil {
|
||||||
|
|
Loading…
Add table
Reference in a new issue