summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--cli_args.go3
-rwxr-xr-xgocryptfs.gzbin0 -> 1849694 bytes
-rw-r--r--internal/speed/speed.go120
-rw-r--r--internal/speed/speed_test.go29
-rw-r--r--internal/stupidgcm/stupidgcm_test.go58
-rw-r--r--main.go6
7 files changed, 158 insertions, 59 deletions
diff --git a/.travis.yml b/.travis.yml
index 5fea238..20fc6c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,6 +20,7 @@ script:
- go build
- ./build-without-openssl.bash
- ./build.bash
+ - ./gocryptfs -speed
- ./test.bash
# fuse on travis
diff --git a/cli_args.go b/cli_args.go
index 25392c4..f52d265 100644
--- a/cli_args.go
+++ b/cli_args.go
@@ -18,7 +18,7 @@ type argContainer struct {
debug, init, zerokey, fusedebug, openssl, passwd, fg, version,
plaintextnames, quiet, nosyslog, wpanic,
longnames, allow_other, ro, reverse, aessiv, nonempty, raw64,
- noprealloc bool
+ noprealloc, speed bool
masterkey, mountpoint, cipherdir, cpuprofile, extpass,
memprofile, ko, passfile, ctlsock, fsname string
// Configuration file name override
@@ -110,6 +110,7 @@ func parseCliOpts() (args argContainer) {
flagSet.BoolVar(&args.nonempty, "nonempty", false, "Allow mounting over non-empty directories")
flagSet.BoolVar(&args.raw64, "raw64", false, "Use unpadded base64 for file names")
flagSet.BoolVar(&args.noprealloc, "noprealloc", false, "Disable preallocation before writing")
+ flagSet.BoolVar(&args.speed, "speed", false, "Run crypto speed test")
flagSet.StringVar(&args.masterkey, "masterkey", "", "Mount with explicit master key")
flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file")
flagSet.StringVar(&args.memprofile, "memprofile", "", "Write memory profile to specified file")
diff --git a/gocryptfs.gz b/gocryptfs.gz
new file mode 100755
index 0000000..9c90b18
--- /dev/null
+++ b/gocryptfs.gz
Binary files differ
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)
- }
-}
diff --git a/main.go b/main.go
index 21f2d06..9301ae1 100644
--- a/main.go
+++ b/main.go
@@ -13,6 +13,7 @@ import (
"github.com/rfjakob/gocryptfs/internal/configfile"
"github.com/rfjakob/gocryptfs/internal/contentenc"
"github.com/rfjakob/gocryptfs/internal/readpassword"
+ "github.com/rfjakob/gocryptfs/internal/speed"
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
"github.com/rfjakob/gocryptfs/internal/tlog"
)
@@ -149,6 +150,11 @@ func main() {
printVersion()
os.Exit(0)
}
+ // "-speed"
+ if args.speed {
+ speed.Run()
+ os.Exit(0)
+ }
if args.wpanic {
tlog.Warn.Wpanic = true
tlog.Debug.Printf("Panicing on warnings")