diff options
Diffstat (limited to 'internal/speed/speed.go')
-rw-r--r-- | internal/speed/speed.go | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/internal/speed/speed.go b/internal/speed/speed.go new file mode 100644 index 0000000..f9bf93c --- /dev/null +++ b/internal/speed/speed.go @@ -0,0 +1,120 @@ +// Package speed implements the "-speed" command-line option, +// similar to "openssl speed". +// It benchmarks the crypto algorithms and libraries used by +// gocryptfs. +package speed + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "fmt" + "log" + "testing" + + "github.com/rfjakob/gocryptfs/internal/prefer_openssl" + "github.com/rfjakob/gocryptfs/internal/siv_aead" + "github.com/rfjakob/gocryptfs/internal/stupidgcm" +) + +func Run() { + bTable := []struct { + name string + f func(*testing.B) + preferred bool + }{ + {name: "AES-GCM-256-OpenSSL", f: bStupidGCM, preferred: prefer_openssl.PreferOpenSSL()}, + {name: "AES-GCM-256-Go", f: bGoGCM, preferred: !prefer_openssl.PreferOpenSSL()}, + {name: "AES-SIV-512-Go", f: bAESSIV, preferred: false}, + } + for _, b := range bTable { + fmt.Printf("%-20s\t", b.name) + mbs := mbPerSec(testing.Benchmark(b.f)) + if mbs > 0 { + fmt.Printf("%7.2f MB/s", mbs) + } else { + fmt.Printf(" N/A") + } + if b.preferred { + fmt.Printf("\t(selected in auto mode)\n") + } else { + fmt.Printf("\t\n") + } + } +} + +func mbPerSec(r testing.BenchmarkResult) float64 { + if r.Bytes <= 0 || r.T <= 0 || r.N <= 0 { + return 0 + } + return (float64(r.Bytes) * float64(r.N) / 1e6) / r.T.Seconds() +} + +// Get "n" random bytes from /dev/urandom or panic +func randBytes(n int) []byte { + b := make([]byte, n) + _, err := rand.Read(b) + if err != nil { + log.Panic("Failed to read random bytes: " + err.Error()) + } + return b +} + +const blockSize = 4096 + +func bStupidGCM(b *testing.B) { + if stupidgcm.BuiltWithoutOpenssl { + b.Skip("openssl has been disabled at compile-time") + } + key := randBytes(32) + authData := randBytes(24) + iv := randBytes(16) + in := make([]byte, blockSize) + b.SetBytes(int64(len(in))) + + sGCM := stupidgcm.New(key) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + // Encrypt and append to nonce + sGCM.Seal(iv, iv, in, authData) + } +} + +func bGoGCM(b *testing.B) { + key := randBytes(32) + authData := randBytes(24) + iv := randBytes(16) + in := make([]byte, blockSize) + b.SetBytes(int64(len(in))) + + gAES, err := aes.NewCipher(key) + if err != nil { + b.Fatal(err) + } + gGCM, err := cipher.NewGCMWithNonceSize(gAES, 16) + if err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + // Encrypt and append to nonce + gGCM.Seal(iv, iv, in, authData) + } +} + +func bAESSIV(b *testing.B) { + key := randBytes(64) + authData := randBytes(24) + iv := randBytes(16) + in := make([]byte, blockSize) + b.SetBytes(int64(len(in))) + gGCM := siv_aead.New(key) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + // Encrypt and append to nonce + gGCM.Seal(iv, iv, in, authData) + } +} |