1// Copyright 2013 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 5package cipher_test 6 7import ( 8 "crypto/aes" 9 "crypto/cipher" 10 "strconv" 11 "testing" 12) 13 14func benchmarkAESGCMSeal(b *testing.B, buf []byte, keySize int) { 15 b.ReportAllocs() 16 b.SetBytes(int64(len(buf))) 17 18 var key = make([]byte, keySize) 19 var nonce [12]byte 20 var ad [13]byte 21 aes, _ := aes.NewCipher(key[:]) 22 aesgcm, _ := cipher.NewGCM(aes) 23 var out []byte 24 25 b.ResetTimer() 26 for i := 0; i < b.N; i++ { 27 out = aesgcm.Seal(out[:0], nonce[:], buf, ad[:]) 28 } 29} 30 31func benchmarkAESGCMOpen(b *testing.B, buf []byte, keySize int) { 32 b.ReportAllocs() 33 b.SetBytes(int64(len(buf))) 34 35 var key = make([]byte, keySize) 36 var nonce [12]byte 37 var ad [13]byte 38 aes, _ := aes.NewCipher(key[:]) 39 aesgcm, _ := cipher.NewGCM(aes) 40 var out []byte 41 42 ct := aesgcm.Seal(nil, nonce[:], buf[:], ad[:]) 43 44 b.ResetTimer() 45 for i := 0; i < b.N; i++ { 46 out, _ = aesgcm.Open(out[:0], nonce[:], ct, ad[:]) 47 } 48} 49 50func BenchmarkAESGCM(b *testing.B) { 51 for _, length := range []int{64, 1350, 8 * 1024} { 52 b.Run("Open-128-"+strconv.Itoa(length), func(b *testing.B) { 53 benchmarkAESGCMOpen(b, make([]byte, length), 128/8) 54 }) 55 b.Run("Seal-128-"+strconv.Itoa(length), func(b *testing.B) { 56 benchmarkAESGCMSeal(b, make([]byte, length), 128/8) 57 }) 58 59 b.Run("Open-256-"+strconv.Itoa(length), func(b *testing.B) { 60 benchmarkAESGCMOpen(b, make([]byte, length), 256/8) 61 }) 62 b.Run("Seal-256-"+strconv.Itoa(length), func(b *testing.B) { 63 benchmarkAESGCMSeal(b, make([]byte, length), 256/8) 64 }) 65 } 66} 67 68func benchmarkAESStream(b *testing.B, mode func(cipher.Block, []byte) cipher.Stream, buf []byte) { 69 b.SetBytes(int64(len(buf))) 70 71 var key [16]byte 72 var iv [16]byte 73 aes, _ := aes.NewCipher(key[:]) 74 stream := mode(aes, iv[:]) 75 76 b.ResetTimer() 77 for i := 0; i < b.N; i++ { 78 stream.XORKeyStream(buf, buf) 79 } 80} 81 82// If we test exactly 1K blocks, we would generate exact multiples of 83// the cipher's block size, and the cipher stream fragments would 84// always be wordsize aligned, whereas non-aligned is a more typical 85// use-case. 86const almost1K = 1024 - 5 87const almost8K = 8*1024 - 5 88 89func BenchmarkAESCFBEncrypt1K(b *testing.B) { 90 benchmarkAESStream(b, cipher.NewCFBEncrypter, make([]byte, almost1K)) 91} 92 93func BenchmarkAESCFBDecrypt1K(b *testing.B) { 94 benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost1K)) 95} 96 97func BenchmarkAESCFBDecrypt8K(b *testing.B) { 98 benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost8K)) 99} 100 101func BenchmarkAESOFB1K(b *testing.B) { 102 benchmarkAESStream(b, cipher.NewOFB, make([]byte, almost1K)) 103} 104 105func BenchmarkAESCTR1K(b *testing.B) { 106 benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost1K)) 107} 108 109func BenchmarkAESCTR8K(b *testing.B) { 110 benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost8K)) 111} 112 113func BenchmarkAESCBCEncrypt1K(b *testing.B) { 114 buf := make([]byte, 1024) 115 b.SetBytes(int64(len(buf))) 116 117 var key [16]byte 118 var iv [16]byte 119 aes, _ := aes.NewCipher(key[:]) 120 cbc := cipher.NewCBCEncrypter(aes, iv[:]) 121 for i := 0; i < b.N; i++ { 122 cbc.CryptBlocks(buf, buf) 123 } 124} 125 126func BenchmarkAESCBCDecrypt1K(b *testing.B) { 127 buf := make([]byte, 1024) 128 b.SetBytes(int64(len(buf))) 129 130 var key [16]byte 131 var iv [16]byte 132 aes, _ := aes.NewCipher(key[:]) 133 cbc := cipher.NewCBCDecrypter(aes, iv[:]) 134 for i := 0; i < b.N; i++ { 135 cbc.CryptBlocks(buf, buf) 136 } 137} 138