Home | History | Annotate | Download | only in chacha20poly1305
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package chacha20poly1305
      6 
      7 import (
      8 	"bytes"
      9 	cr "crypto/rand"
     10 	"encoding/hex"
     11 	mr "math/rand"
     12 	"testing"
     13 )
     14 
     15 func TestVectors(t *testing.T) {
     16 	for i, test := range chacha20Poly1305Tests {
     17 		key, _ := hex.DecodeString(test.key)
     18 		nonce, _ := hex.DecodeString(test.nonce)
     19 		ad, _ := hex.DecodeString(test.aad)
     20 		plaintext, _ := hex.DecodeString(test.plaintext)
     21 
     22 		aead, err := New(key)
     23 		if err != nil {
     24 			t.Fatal(err)
     25 		}
     26 
     27 		ct := aead.Seal(nil, nonce, plaintext, ad)
     28 		if ctHex := hex.EncodeToString(ct); ctHex != test.out {
     29 			t.Errorf("#%d: got %s, want %s", i, ctHex, test.out)
     30 			continue
     31 		}
     32 
     33 		plaintext2, err := aead.Open(nil, nonce, ct, ad)
     34 		if err != nil {
     35 			t.Errorf("#%d: Open failed", i)
     36 			continue
     37 		}
     38 
     39 		if !bytes.Equal(plaintext, plaintext2) {
     40 			t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
     41 			continue
     42 		}
     43 
     44 		if len(ad) > 0 {
     45 			alterAdIdx := mr.Intn(len(ad))
     46 			ad[alterAdIdx] ^= 0x80
     47 			if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
     48 				t.Errorf("#%d: Open was successful after altering additional data", i)
     49 			}
     50 			ad[alterAdIdx] ^= 0x80
     51 		}
     52 
     53 		alterNonceIdx := mr.Intn(aead.NonceSize())
     54 		nonce[alterNonceIdx] ^= 0x80
     55 		if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
     56 			t.Errorf("#%d: Open was successful after altering nonce", i)
     57 		}
     58 		nonce[alterNonceIdx] ^= 0x80
     59 
     60 		alterCtIdx := mr.Intn(len(ct))
     61 		ct[alterCtIdx] ^= 0x80
     62 		if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
     63 			t.Errorf("#%d: Open was successful after altering ciphertext", i)
     64 		}
     65 		ct[alterCtIdx] ^= 0x80
     66 	}
     67 }
     68 
     69 func TestRandom(t *testing.T) {
     70 	// Some random tests to verify Open(Seal) == Plaintext
     71 	for i := 0; i < 256; i++ {
     72 		var nonce [12]byte
     73 		var key [32]byte
     74 
     75 		al := mr.Intn(128)
     76 		pl := mr.Intn(16384)
     77 		ad := make([]byte, al)
     78 		plaintext := make([]byte, pl)
     79 		cr.Read(key[:])
     80 		cr.Read(nonce[:])
     81 		cr.Read(ad)
     82 		cr.Read(plaintext)
     83 
     84 		aead, err := New(key[:])
     85 		if err != nil {
     86 			t.Fatal(err)
     87 		}
     88 
     89 		ct := aead.Seal(nil, nonce[:], plaintext, ad)
     90 
     91 		plaintext2, err := aead.Open(nil, nonce[:], ct, ad)
     92 		if err != nil {
     93 			t.Errorf("Random #%d: Open failed", i)
     94 			continue
     95 		}
     96 
     97 		if !bytes.Equal(plaintext, plaintext2) {
     98 			t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
     99 			continue
    100 		}
    101 
    102 		if len(ad) > 0 {
    103 			alterAdIdx := mr.Intn(len(ad))
    104 			ad[alterAdIdx] ^= 0x80
    105 			if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
    106 				t.Errorf("Random #%d: Open was successful after altering additional data", i)
    107 			}
    108 			ad[alterAdIdx] ^= 0x80
    109 		}
    110 
    111 		alterNonceIdx := mr.Intn(aead.NonceSize())
    112 		nonce[alterNonceIdx] ^= 0x80
    113 		if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
    114 			t.Errorf("Random #%d: Open was successful after altering nonce", i)
    115 		}
    116 		nonce[alterNonceIdx] ^= 0x80
    117 
    118 		alterCtIdx := mr.Intn(len(ct))
    119 		ct[alterCtIdx] ^= 0x80
    120 		if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
    121 			t.Errorf("Random #%d: Open was successful after altering ciphertext", i)
    122 		}
    123 		ct[alterCtIdx] ^= 0x80
    124 	}
    125 }
    126 
    127 func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte) {
    128 	b.SetBytes(int64(len(buf)))
    129 
    130 	var key [32]byte
    131 	var nonce [12]byte
    132 	var ad [13]byte
    133 	var out []byte
    134 
    135 	aead, _ := New(key[:])
    136 	b.ResetTimer()
    137 	for i := 0; i < b.N; i++ {
    138 		out = aead.Seal(out[:0], nonce[:], buf[:], ad[:])
    139 	}
    140 }
    141 
    142 func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte) {
    143 	b.SetBytes(int64(len(buf)))
    144 
    145 	var key [32]byte
    146 	var nonce [12]byte
    147 	var ad [13]byte
    148 	var ct []byte
    149 	var out []byte
    150 
    151 	aead, _ := New(key[:])
    152 	ct = aead.Seal(ct[:0], nonce[:], buf[:], ad[:])
    153 
    154 	b.ResetTimer()
    155 	for i := 0; i < b.N; i++ {
    156 		out, _ = aead.Open(out[:0], nonce[:], ct[:], ad[:])
    157 	}
    158 }
    159 
    160 func BenchmarkChacha20Poly1305Open_64(b *testing.B) {
    161 	benchamarkChaCha20Poly1305Open(b, make([]byte, 64))
    162 }
    163 
    164 func BenchmarkChacha20Poly1305Seal_64(b *testing.B) {
    165 	benchamarkChaCha20Poly1305Seal(b, make([]byte, 64))
    166 }
    167 
    168 func BenchmarkChacha20Poly1305Open_1350(b *testing.B) {
    169 	benchamarkChaCha20Poly1305Open(b, make([]byte, 1350))
    170 }
    171 
    172 func BenchmarkChacha20Poly1305Seal_1350(b *testing.B) {
    173 	benchamarkChaCha20Poly1305Seal(b, make([]byte, 1350))
    174 }
    175 
    176 func BenchmarkChacha20Poly1305Open_8K(b *testing.B) {
    177 	benchamarkChaCha20Poly1305Open(b, make([]byte, 8*1024))
    178 }
    179 
    180 func BenchmarkChacha20Poly1305Seal_8K(b *testing.B) {
    181 	benchamarkChaCha20Poly1305Seal(b, make([]byte, 8*1024))
    182 }
    183