aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorJakob Unterwurzacher2017-02-22 23:55:43 +0100
committerJakob Unterwurzacher2017-02-22 23:56:34 +0100
commit1e03e059fa0980db8d527f1c01094999d8813b95 (patch)
tree950f537f1fa58e9f0506a540b31d790030e69a1d /internal
parentb056776a013813e251aa37027c3aaa3f1e22d7c8 (diff)
Implement "gocryptfs -speed"
A crypto benchmark mode like "openssl speed". Example run: $ ./gocryptfs -speed AES-GCM-256-OpenSSL 180.89 MB/s (selected in auto mode) AES-GCM-256-Go 48.19 MB/s AES-SIV-512-Go 37.40 MB/s
Diffstat (limited to 'internal')
-rw-r--r--internal/speed/speed.go120
-rw-r--r--internal/speed/speed_test.go29
-rw-r--r--internal/stupidgcm/stupidgcm_test.go58
3 files changed, 149 insertions, 58 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)
+ }
+}
diff --git a/internal/speed/speed_test.go b/internal/speed/speed_test.go
new file mode 100644
index 0000000..1e9d859
--- /dev/null
+++ b/internal/speed/speed_test.go
@@ -0,0 +1,29 @@
+package speed
+
+/*
+Make the "-speed" benchmarks also accessible to the standard test system.
+Example run:
+
+$ go test -bench .
+BenchmarkStupidGCM-2 100000 22552 ns/op 181.62 MB/s
+BenchmarkGoGCM-2 20000 81871 ns/op 50.03 MB/s
+BenchmarkAESSIV-2 10000 104623 ns/op 39.15 MB/s
+PASS
+ok github.com/rfjakob/gocryptfs/internal/speed 6.022s
+*/
+
+import (
+ "testing"
+)
+
+func BenchmarkStupidGCM(b *testing.B) {
+ bStupidGCM(b)
+}
+
+func BenchmarkGoGCM(b *testing.B) {
+ bGoGCM(b)
+}
+
+func BenchmarkAESSIV(b *testing.B) {
+ bAESSIV(b)
+}
diff --git a/internal/stupidgcm/stupidgcm_test.go b/internal/stupidgcm/stupidgcm_test.go
index d6c0714..ba25855 100644
--- a/internal/stupidgcm/stupidgcm_test.go
+++ b/internal/stupidgcm/stupidgcm_test.go
@@ -15,9 +15,6 @@ import (
"encoding/hex"
"log"
"testing"
-
- // For benchmark comparison
- "github.com/rfjakob/gocryptfs/internal/siv_aead"
)
// Get "n" random bytes from /dev/urandom or panic
@@ -121,58 +118,3 @@ func TestCorruption(t *testing.T) {
t.Fatalf("Should have gotten error")
}
}
-
-// $ go test -bench .
-// PASS
-// Benchmark4kEncStupidGCM-2 50000 25622 ns/op 159.86 MB/s
-// Benchmark4kEncGoGCM-2 10000 116544 ns/op 35.15 MB/s
-// ok github.com/rfjakob/gocryptfs/internal/stupidgcm 3.775s
-func Benchmark4kEncStupidGCM(b *testing.B) {
- key := randBytes(32)
- authData := randBytes(24)
- iv := randBytes(16)
- in := make([]byte, 4096)
- b.SetBytes(int64(len(in)))
-
- sGCM := New(key)
-
- for i := 0; i < b.N; i++ {
- // Encrypt and append to nonce
- sGCM.Seal(iv, iv, in, authData)
- }
-}
-
-func Benchmark4kEncGoGCM(b *testing.B) {
- key := randBytes(32)
- authData := randBytes(24)
- iv := randBytes(16)
- in := make([]byte, 4096)
- 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)
- }
-
- for i := 0; i < b.N; i++ {
- // Encrypt and append to nonce
- gGCM.Seal(iv, iv, in, authData)
- }
-}
-
-func Benchmark4kEncAESSIV(b *testing.B) {
- key := randBytes(32)
- authData := randBytes(24)
- iv := randBytes(16)
- in := make([]byte, 4096)
- b.SetBytes(int64(len(in)))
- gGCM := siv_aead.New(key)
- for i := 0; i < b.N; i++ {
- // Encrypt and append to nonce
- gGCM.Seal(iv, iv, in, authData)
- }
-}