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
This commit is contained in:
parent
b056776a01
commit
1e03e059fa
@ -20,6 +20,7 @@ script:
|
|||||||
- go build
|
- go build
|
||||||
- ./build-without-openssl.bash
|
- ./build-without-openssl.bash
|
||||||
- ./build.bash
|
- ./build.bash
|
||||||
|
- ./gocryptfs -speed
|
||||||
- ./test.bash
|
- ./test.bash
|
||||||
|
|
||||||
# fuse on travis
|
# fuse on travis
|
||||||
|
@ -18,7 +18,7 @@ type argContainer struct {
|
|||||||
debug, init, zerokey, fusedebug, openssl, passwd, fg, version,
|
debug, init, zerokey, fusedebug, openssl, passwd, fg, version,
|
||||||
plaintextnames, quiet, nosyslog, wpanic,
|
plaintextnames, quiet, nosyslog, wpanic,
|
||||||
longnames, allow_other, ro, reverse, aessiv, nonempty, raw64,
|
longnames, allow_other, ro, reverse, aessiv, nonempty, raw64,
|
||||||
noprealloc bool
|
noprealloc, speed bool
|
||||||
masterkey, mountpoint, cipherdir, cpuprofile, extpass,
|
masterkey, mountpoint, cipherdir, cpuprofile, extpass,
|
||||||
memprofile, ko, passfile, ctlsock, fsname string
|
memprofile, ko, passfile, ctlsock, fsname string
|
||||||
// Configuration file name override
|
// 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.nonempty, "nonempty", false, "Allow mounting over non-empty directories")
|
||||||
flagSet.BoolVar(&args.raw64, "raw64", false, "Use unpadded base64 for file names")
|
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.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.masterkey, "masterkey", "", "Mount with explicit master key")
|
||||||
flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file")
|
flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file")
|
||||||
flagSet.StringVar(&args.memprofile, "memprofile", "", "Write memory profile to specified file")
|
flagSet.StringVar(&args.memprofile, "memprofile", "", "Write memory profile to specified file")
|
||||||
|
BIN
gocryptfs.gz
Executable file
BIN
gocryptfs.gz
Executable file
Binary file not shown.
120
internal/speed/speed.go
Normal file
120
internal/speed/speed.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
29
internal/speed/speed_test.go
Normal file
29
internal/speed/speed_test.go
Normal file
@ -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)
|
||||||
|
}
|
@ -15,9 +15,6 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"log"
|
"log"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
// For benchmark comparison
|
|
||||||
"github.com/rfjakob/gocryptfs/internal/siv_aead"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get "n" random bytes from /dev/urandom or panic
|
// Get "n" random bytes from /dev/urandom or panic
|
||||||
@ -121,58 +118,3 @@ func TestCorruption(t *testing.T) {
|
|||||||
t.Fatalf("Should have gotten error")
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
6
main.go
6
main.go
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/rfjakob/gocryptfs/internal/configfile"
|
"github.com/rfjakob/gocryptfs/internal/configfile"
|
||||||
"github.com/rfjakob/gocryptfs/internal/contentenc"
|
"github.com/rfjakob/gocryptfs/internal/contentenc"
|
||||||
"github.com/rfjakob/gocryptfs/internal/readpassword"
|
"github.com/rfjakob/gocryptfs/internal/readpassword"
|
||||||
|
"github.com/rfjakob/gocryptfs/internal/speed"
|
||||||
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
|
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
|
||||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||||
)
|
)
|
||||||
@ -149,6 +150,11 @@ func main() {
|
|||||||
printVersion()
|
printVersion()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
// "-speed"
|
||||||
|
if args.speed {
|
||||||
|
speed.Run()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
if args.wpanic {
|
if args.wpanic {
|
||||||
tlog.Warn.Wpanic = true
|
tlog.Warn.Wpanic = true
|
||||||
tlog.Debug.Printf("Panicing on warnings")
|
tlog.Debug.Printf("Panicing on warnings")
|
||||||
|
Loading…
Reference in New Issue
Block a user