From 71a9165647d0ce7aab8b5dbf8d1acda6977fadc2 Mon Sep 17 00:00:00 2001 From: tdakkota Date: Sun, 6 Jun 2021 21:55:02 +0300 Subject: [PATCH 1/4] chore: add gitignore --- .gitignore | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6fe4ecb --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# IntelliJ project files +.idea +*.iml +out +gen +### Go template +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + From caece34420105a8788aa45a5c3aa2c12c9a2ceb1 Mon Sep 17 00:00:00 2001 From: tdakkota Date: Sun, 6 Jun 2021 22:03:40 +0300 Subject: [PATCH 2/4] test: add benchmarks --- decrypt.go | 9 +++++++++ decrypt_test.go | 36 ++++++++++++++++++++++++++++++++++++ encrypt.go | 9 +++++++++ encrypt_test.go | 36 ++++++++++++++++++++++++++++++++++++ go.sum | 3 +-- 5 files changed, 91 insertions(+), 2 deletions(-) diff --git a/decrypt.go b/decrypt.go index f1b6e39..051dbfc 100644 --- a/decrypt.go +++ b/decrypt.go @@ -48,3 +48,12 @@ func (i *igeDecrypter) CryptBlocks(dst, src []byte) { c = t } } + +// DecryptBlocks is a simple shorthand for IGE decrypting. +func DecryptBlocks(b cipher.Block, iv, dst, src []byte) { + if err := checkIV(b, iv); err != nil { + panic(err.Error()) + } + dec := NewIGEDecrypter(b, iv) + dec.CryptBlocks(dst, src) +} diff --git a/decrypt_test.go b/decrypt_test.go index 7bb03df..61a6b91 100644 --- a/decrypt_test.go +++ b/decrypt_test.go @@ -3,6 +3,7 @@ package ige import ( "bytes" "crypto/aes" + "fmt" "testing" ) @@ -83,3 +84,38 @@ func TestDecryptCryptBlocksPanicDst(t *testing.T) { i := NewIGEDecrypter(c, make([]byte, 32)) i.CryptBlocks(make([]byte, 1), make([]byte, 16)) } + +func BenchmarkDecryptBlocks(b *testing.B) { + for _, payload := range []int{ + 16, + 128, + 1024, + 8192, + 64 * 1024, + 512 * 1024, + } { + b.Run(fmt.Sprintf("%d", payload), benchDecrypt(payload)) + } +} + +func benchDecrypt(n int) func(b *testing.B) { + return func(b *testing.B) { + b.Helper() + + src := make([]byte, n) + dst := make([]byte, n) + + b.ReportAllocs() + b.SetBytes(int64(n)) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + c, err := aes.NewCipher(TestVectors[0].Key) + if err != nil { + b.Fatal(err) + } + + DecryptBlocks(c, TestVectors[0].IV, dst, src) + } + } +} diff --git a/encrypt.go b/encrypt.go index 8da7adf..604464a 100644 --- a/encrypt.go +++ b/encrypt.go @@ -46,3 +46,12 @@ func (i *igeEncrypter) CryptBlocks(dst, src []byte) { m = src[o : o+b] } } + +// EncryptBlocks is a simple shorthand for IGE encrypting. +func EncryptBlocks(b cipher.Block, iv, dst, src []byte) { + if err := checkIV(b, iv); err != nil { + panic(err.Error()) + } + dec := NewIGEEncrypter(b, iv) + dec.CryptBlocks(dst, src) +} diff --git a/encrypt_test.go b/encrypt_test.go index 8f99f9d..c7eff26 100644 --- a/encrypt_test.go +++ b/encrypt_test.go @@ -3,6 +3,7 @@ package ige import ( "bytes" "crypto/aes" + "fmt" "testing" ) @@ -83,3 +84,38 @@ func TestEncryptCryptBlocksPanicDst(t *testing.T) { i := NewIGEEncrypter(c, make([]byte, 32)) i.CryptBlocks(make([]byte, 1), make([]byte, 16)) } + +func BenchmarkEncryptBlocks(b *testing.B) { + for _, payload := range []int{ + 16, + 128, + 1024, + 8192, + 64 * 1024, + 512 * 1024, + } { + b.Run(fmt.Sprintf("%d", payload), benchEncrypt(payload)) + } +} + +func benchEncrypt(n int) func(b *testing.B) { + return func(b *testing.B) { + b.Helper() + + src := make([]byte, n) + dst := make([]byte, n) + + b.ReportAllocs() + b.SetBytes(int64(n)) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + c, err := aes.NewCipher(TestVectors[0].Key) + if err != nil { + b.Fatal(err) + } + + EncryptBlocks(c, TestVectors[0].IV, dst, src) + } + } +} diff --git a/go.sum b/go.sum index bfba2a0..f426987 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,2 @@ -github.com/gotd/xor v0.1.0 h1:kg9XdEeTpbZbvsyjQq2l+UbgvZanJFRSazrI06+qXG0= -github.com/gotd/xor v0.1.0/go.mod h1:ZTmdgqf6SOHder8/MFp9CNkXIadzID5lIiaZxRZICH0= +github.com/gotd/xor v0.1.1 h1:LSPEeuf7noTo4fi4PrEsAaWXOSwjsY2e+IINPiR+c7s= github.com/gotd/xor v0.1.1/go.mod h1:ZTmdgqf6SOHder8/MFp9CNkXIadzID5lIiaZxRZICH0= From ee9db414e0bcc2e527e644e7ffbc765342be63fd Mon Sep 17 00:00:00 2001 From: tdakkota Date: Sun, 6 Jun 2021 22:51:09 +0300 Subject: [PATCH 3/4] feat(ige): reduce allocations for DecryptBlocks/EncryptBlocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Do not copy iv - Create ige without constructor, prevent leaking as interface Benchstat results: name old time/op new time/op delta DecryptBlocks/16-4 1.26µs ± 2% 1.01µs ± 4% -20.15% (p=0.008 n=5+5) DecryptBlocks/128-4 2.16µs ± 2% 1.73µs ± 1% -19.79% (p=0.008 n=5+5) DecryptBlocks/1024-4 9.23µs ± 4% 7.60µs ± 2% -17.66% (p=0.008 n=5+5) DecryptBlocks/8192-4 64.9µs ± 3% 54.1µs ± 1% -16.59% (p=0.008 n=5+5) DecryptBlocks/65536-4 571µs ±22% 431µs ± 2% -24.48% (p=0.008 n=5+5) DecryptBlocks/524288-4 3.83ms ±14% 3.44ms ± 2% -10.33% (p=0.008 n=5+5) EncryptBlocks/16-4 1.11µs ± 8% 0.99µs ± 2% -10.53% (p=0.008 n=5+5) EncryptBlocks/128-4 1.95µs ± 7% 1.75µs ± 2% -10.45% (p=0.008 n=5+5) EncryptBlocks/1024-4 8.32µs ±10% 7.81µs ± 2% -6.19% (p=0.008 n=5+5) EncryptBlocks/8192-4 60.6µs ±19% 55.5µs ± 0% -8.45% (p=0.008 n=5+5) EncryptBlocks/65536-4 446µs ± 4% 438µs ± 2% ~ (p=0.056 n=5+5) EncryptBlocks/524288-4 3.62ms ± 9% 3.57ms ± 2% ~ (p=1.000 n=5+5) name old speed new speed delta DecryptBlocks/16-4 12.7MB/s ± 2% 15.9MB/s ± 4% +25.32% (p=0.008 n=5+5) DecryptBlocks/128-4 59.3MB/s ± 2% 73.9MB/s ± 1% +24.66% (p=0.008 n=5+5) DecryptBlocks/1024-4 111MB/s ± 4% 135MB/s ± 2% +21.41% (p=0.008 n=5+5) DecryptBlocks/8192-4 126MB/s ± 3% 151MB/s ± 1% +19.84% (p=0.008 n=5+5) DecryptBlocks/65536-4 116MB/s ±19% 152MB/s ± 2% +30.85% (p=0.008 n=5+5) DecryptBlocks/524288-4 138MB/s ±13% 152MB/s ± 2% +10.50% (p=0.008 n=5+5) EncryptBlocks/16-4 14.4MB/s ± 8% 16.1MB/s ± 1% +11.65% (p=0.008 n=5+5) EncryptBlocks/128-4 65.6MB/s ± 7% 73.1MB/s ± 2% +11.42% (p=0.008 n=5+5) EncryptBlocks/1024-4 123MB/s ± 9% 131MB/s ± 2% +6.35% (p=0.008 n=5+5) EncryptBlocks/8192-4 136MB/s ±17% 148MB/s ± 0% +8.35% (p=0.008 n=5+5) EncryptBlocks/65536-4 147MB/s ± 4% 150MB/s ± 2% ~ (p=0.056 n=5+5) EncryptBlocks/524288-4 145MB/s ± 8% 147MB/s ± 2% ~ (p=1.000 n=5+5) name old alloc/op new alloc/op delta DecryptBlocks/16-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) DecryptBlocks/128-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) DecryptBlocks/1024-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) DecryptBlocks/8192-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) DecryptBlocks/65536-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) DecryptBlocks/524288-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) EncryptBlocks/16-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) EncryptBlocks/128-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) EncryptBlocks/1024-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) EncryptBlocks/8192-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) EncryptBlocks/65536-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) EncryptBlocks/524288-4 480B ± 0% 400B ± 0% -16.67% (p=0.008 n=5+5) name old allocs/op new allocs/op delta DecryptBlocks/16-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) DecryptBlocks/128-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) DecryptBlocks/1024-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) DecryptBlocks/8192-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) DecryptBlocks/65536-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) DecryptBlocks/524288-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) EncryptBlocks/16-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) EncryptBlocks/128-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) EncryptBlocks/1024-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) EncryptBlocks/8192-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) EncryptBlocks/65536-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) EncryptBlocks/524288-4 5.00 ± 0% 3.00 ± 0% -40.00% (p=0.008 n=5+5) --- decrypt.go | 4 +++- encrypt.go | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/decrypt.go b/decrypt.go index 051dbfc..09e8cb9 100644 --- a/decrypt.go +++ b/decrypt.go @@ -50,10 +50,12 @@ func (i *igeDecrypter) CryptBlocks(dst, src []byte) { } // DecryptBlocks is a simple shorthand for IGE decrypting. +// Note: unlike NewIGEDecrypter, DecryptBlocks does NOT COPY iv. +// So you must not modify passed iv. func DecryptBlocks(b cipher.Block, iv, dst, src []byte) { if err := checkIV(b, iv); err != nil { panic(err.Error()) } - dec := NewIGEDecrypter(b, iv) + dec := igeDecrypter{block: b, iv: iv} dec.CryptBlocks(dst, src) } diff --git a/encrypt.go b/encrypt.go index 604464a..ac07ba0 100644 --- a/encrypt.go +++ b/encrypt.go @@ -48,10 +48,12 @@ func (i *igeEncrypter) CryptBlocks(dst, src []byte) { } // EncryptBlocks is a simple shorthand for IGE encrypting. +// Note: unlike NewIGEEncrypter, EncryptBlocks does NOT COPY iv. +// So you must not modify passed iv. func EncryptBlocks(b cipher.Block, iv, dst, src []byte) { if err := checkIV(b, iv); err != nil { panic(err.Error()) } - dec := NewIGEEncrypter(b, iv) - dec.CryptBlocks(dst, src) + enc := igeEncrypter{block: b, iv: iv} + enc.CryptBlocks(dst, src) } From 05915c891ede3d4d678fb62d3ba4da82893f243d Mon Sep 17 00:00:00 2001 From: tdakkota Date: Sun, 6 Jun 2021 22:56:37 +0300 Subject: [PATCH 4/4] test: add tests for DecryptBlocks and EncryptBlocks --- decrypt_test.go | 17 +++++++++++++++++ encrypt_test.go | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/decrypt_test.go b/decrypt_test.go index 61a6b91..180f206 100644 --- a/decrypt_test.go +++ b/decrypt_test.go @@ -53,6 +53,23 @@ func TestDecrypterCryptBlocks(t *testing.T) { } } +func TestDecryptBlocks(t *testing.T) { + for a, v := range TestVectors { + out := make([]byte, len(v.Ciphertext)) + + c, err := aes.NewCipher(v.Key) + if err != nil { + t.Fatal(err) + } + + DecryptBlocks(c, v.IV, out, v.Ciphertext) + + if !bytes.Equal(out, v.Plaintext) { + t.Fatalf("test vector %d has wrong ciphertext\n", a+1) + } + } +} + func TestDecryptCryptBlocksPanicSrc(t *testing.T) { c, err := aes.NewCipher(make([]byte, 16)) if err != nil { diff --git a/encrypt_test.go b/encrypt_test.go index c7eff26..366bff4 100644 --- a/encrypt_test.go +++ b/encrypt_test.go @@ -53,6 +53,23 @@ func TestEncrypterCryptBlocks(t *testing.T) { } } +func TestEncryptBlocks(t *testing.T) { + for a, v := range TestVectors { + out := make([]byte, len(v.Ciphertext)) + + c, err := aes.NewCipher(v.Key) + if err != nil { + t.Fatal(err) + } + + EncryptBlocks(c, v.IV, out, v.Plaintext) + + if !bytes.Equal(out, v.Ciphertext) { + t.Fatalf("test vector %d has wrong ciphertext\n", a+1) + } + } +} + func TestEncryptCryptBlocksPanicSrc(t *testing.T) { c, err := aes.NewCipher(make([]byte, 16)) if err != nil {