From a86f05e390800138c5e7de0967bebe4815765d1e Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 19 Sep 2022 15:33:49 +0200 Subject: [PATCH] crypto/rsa: improve benchmarks Change-Id: Idee03a0c3e4bdb7d6b495f567db8bd644af480e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/433476 Run-TryBot: Filippo Valsorda Auto-Submit: Filippo Valsorda Reviewed-by: Michael Knyszek TryBot-Result: Gopher Robot Reviewed-by: Roland Shoemaker --- src/crypto/rsa/boring_test.go | 18 ++ src/crypto/rsa/example_test.go | 13 +- src/crypto/rsa/pkcs1v15_test.go | 52 ++-- src/crypto/rsa/pss_test.go | 11 +- src/crypto/rsa/rsa_export_test.go | 10 + src/crypto/rsa/rsa_test.go | 388 ++++++++++++++++++++++-------- 6 files changed, 353 insertions(+), 139 deletions(-) create mode 100644 src/crypto/rsa/rsa_export_test.go diff --git a/src/crypto/rsa/boring_test.go b/src/crypto/rsa/boring_test.go index 6223244283..2234d079f0 100644 --- a/src/crypto/rsa/boring_test.go +++ b/src/crypto/rsa/boring_test.go @@ -13,6 +13,8 @@ import ( "crypto" "crypto/rand" "encoding/asn1" + "encoding/hex" + "math/big" "runtime" "runtime/debug" "sync" @@ -128,3 +130,19 @@ func TestBoringFinalizers(t *testing.T) { wg.Wait() } } + +func bigFromHex(hex string) *big.Int { + n, ok := new(big.Int).SetString(hex, 16) + if !ok { + panic("bad hex: " + hex) + } + return n +} + +func fromHex(hexStr string) []byte { + s, err := hex.DecodeString(hexStr) + if err != nil { + panic(err) + } + return s +} diff --git a/src/crypto/rsa/example_test.go b/src/crypto/rsa/example_test.go index ce5c2d91cd..8c3a997346 100644 --- a/src/crypto/rsa/example_test.go +++ b/src/crypto/rsa/example_test.go @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package rsa +package rsa_test import ( "crypto" "crypto/aes" "crypto/cipher" "crypto/rand" + "crypto/rsa" "crypto/sha256" "encoding/hex" "fmt" @@ -50,7 +51,7 @@ func ExampleDecryptPKCS1v15SessionKey() { rsaCiphertext, _ := hex.DecodeString("aabbccddeeff") - if err := DecryptPKCS1v15SessionKey(rng, rsaPrivateKey, rsaCiphertext, key); err != nil { + if err := rsa.DecryptPKCS1v15SessionKey(rng, rsaPrivateKey, rsaCiphertext, key); err != nil { // Any errors that result will be “public” – meaning that they // can be determined without any secret information. (For // instance, if the length of key is impossible given the RSA @@ -99,7 +100,7 @@ func ExampleSignPKCS1v15() { // of writing (2016). hashed := sha256.Sum256(message) - signature, err := SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA256, hashed[:]) + signature, err := rsa.SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA256, hashed[:]) if err != nil { fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err) return @@ -119,7 +120,7 @@ func ExampleVerifyPKCS1v15() { // of writing (2016). hashed := sha256.Sum256(message) - err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA256, hashed[:], signature) + err := rsa.VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA256, hashed[:], signature) if err != nil { fmt.Fprintf(os.Stderr, "Error from verification: %s\n", err) return @@ -136,7 +137,7 @@ func ExampleEncryptOAEP() { // encryption function. rng := rand.Reader - ciphertext, err := EncryptOAEP(sha256.New(), rng, &test2048Key.PublicKey, secretMessage, label) + ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, &test2048Key.PublicKey, secretMessage, label) if err != nil { fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err) return @@ -155,7 +156,7 @@ func ExampleDecryptOAEP() { // operation. rng := rand.Reader - plaintext, err := DecryptOAEP(sha256.New(), rng, test2048Key, ciphertext, label) + plaintext, err := rsa.DecryptOAEP(sha256.New(), rng, test2048Key, ciphertext, label) if err != nil { fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err) return diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go index 69c509a771..dfa1eddc88 100644 --- a/src/crypto/rsa/pkcs1v15_test.go +++ b/src/crypto/rsa/pkcs1v15_test.go @@ -2,18 +2,20 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package rsa +package rsa_test import ( "bytes" "crypto" "crypto/rand" + . "crypto/rsa" "crypto/sha1" "crypto/sha256" + "crypto/x509" "encoding/base64" "encoding/hex" + "encoding/pem" "io" - "math/big" "testing" "testing/quick" ) @@ -170,7 +172,7 @@ func TestNonZeroRandomBytes(t *testing.T) { random := rand.Reader b := make([]byte, 512) - err := nonZeroRandomBytes(b, random) + err := NonZeroRandomBytes(b, random) if err != nil { t.Errorf("returned error: %s", err) } @@ -276,34 +278,30 @@ func TestShortSessionKey(t *testing.T) { } } -// In order to generate new test vectors you'll need the PEM form of this key (and s/TESTING/PRIVATE/): -// -----BEGIN RSA TESTING KEY----- -// MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 -// fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu -// /ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu -// RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ -// EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A -// IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS -// tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V -// -----END RSA TESTING KEY----- +var rsaPrivateKey = parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- +MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 +fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu +/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu +RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ +EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A +IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS +tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V +-----END RSA TESTING KEY-----`)) -var rsaPrivateKey = &PrivateKey{ - PublicKey: PublicKey{ - N: fromBase10("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"), - E: 65537, - }, - D: fromBase10("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"), - Primes: []*big.Int{ - fromBase10("98920366548084643601728869055592650835572950932266967461790948584315647051443"), - fromBase10("94560208308847015747498523884063394671606671904944666360068158221458669711639"), - }, +func parsePublicKey(s string) *PublicKey { + p, _ := pem.Decode([]byte(s)) + k, err := x509.ParsePKCS1PublicKey(p.Bytes) + if err != nil { + panic(err) + } + return k } func TestShortPKCS1v15Signature(t *testing.T) { - pub := &PublicKey{ - E: 65537, - N: fromBase10("8272693557323587081220342447407965471608219912416565371060697606400726784709760494166080686904546560026343451112103559482851304715739629410219358933351333"), - } + pub := parsePublicKey(`-----BEGIN RSA PUBLIC KEY----- +MEgCQQCd9BVzo775lkohasxjnefF1nCMcNoibqIWEVDe/K7M2GSoO4zlSQB+gkix +O3AnTcdHB51iaZpWfxPSnew8yfulAgMBAAE= +-----END RSA PUBLIC KEY-----`) sig, err := hex.DecodeString("193a310d0dcf64094c6e3a00c8219b80ded70535473acff72c08e1222974bb24a93a535b1dc4c59fc0e65775df7ba2007dd20e9193f4c4025a18a7070aee93") if err != nil { t.Fatalf("failed to decode signature: %s", err) diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go index ecc02e47d6..f1f1704369 100644 --- a/src/crypto/rsa/pss_test.go +++ b/src/crypto/rsa/pss_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package rsa +package rsa_test import ( "bufio" @@ -10,6 +10,7 @@ import ( "compress/bzip2" "crypto" "crypto/rand" + . "crypto/rsa" "crypto/sha1" "crypto/sha256" "encoding/hex" @@ -60,7 +61,7 @@ func TestEMSAPSS(t *testing.T) { hash.Write(msg) hashed := hash.Sum(nil) - encoded, err := emsaPSSEncode(hashed, 1023, salt, sha1.New()) + encoded, err := EMSAPSSEncode(hashed, 1023, salt, sha1.New()) if err != nil { t.Errorf("Error from emsaPSSEncode: %s\n", err) } @@ -68,7 +69,7 @@ func TestEMSAPSS(t *testing.T) { t.Errorf("Bad encoding. got %x, want %x", encoded, expected) } - if err = emsaPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil { + if err = EMSAPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil { t.Errorf("Bad verification: %s", err) } } @@ -289,8 +290,8 @@ func TestInvalidPSSSaltLength(t *testing.T) { if _, err := SignPSS(rand.Reader, key, crypto.SHA256, digest[:], &PSSOptions{ SaltLength: -2, Hash: crypto.SHA256, - }); err.Error() != invalidSaltLenErr.Error() { - t.Fatalf("SignPSS unexpected error: got %v, want %v", err, invalidSaltLenErr) + }); err.Error() != InvalidSaltLenErr.Error() { + t.Fatalf("SignPSS unexpected error: got %v, want %v", err, InvalidSaltLenErr) } // We don't check the specific error here, because crypto/rsa and crypto/internal/boring diff --git a/src/crypto/rsa/rsa_export_test.go b/src/crypto/rsa/rsa_export_test.go new file mode 100644 index 0000000000..70406decf1 --- /dev/null +++ b/src/crypto/rsa/rsa_export_test.go @@ -0,0 +1,10 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +var NonZeroRandomBytes = nonZeroRandomBytes +var EMSAPSSEncode = emsaPSSEncode +var EMSAPSSVerify = emsaPSSVerify +var InvalidSaltLenErr = invalidSaltLenErr diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go index 99b2cf5ae8..400f40a031 100644 --- a/src/crypto/rsa/rsa_test.go +++ b/src/crypto/rsa/rsa_test.go @@ -2,17 +2,21 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package rsa +package rsa_test import ( + "bufio" "bytes" "crypto" - "crypto/internal/boring" "crypto/rand" + . "crypto/rsa" "crypto/sha1" "crypto/sha256" + "crypto/x509" + "encoding/pem" "fmt" "math/big" + "strings" "testing" ) @@ -91,17 +95,11 @@ func TestGnuTLSKey(t *testing.T) { // This is a key generated by `certtool --generate-privkey --bits 128`. // It's such that de ≢ 1 mod φ(n), but is congruent mod the order of // the group. - priv := &PrivateKey{ - PublicKey: PublicKey{ - N: fromBase10("290684273230919398108010081414538931343"), - E: 65537, - }, - D: fromBase10("31877380284581499213530787347443987241"), - Primes: []*big.Int{ - fromBase10("16775196964030542637"), - fromBase10("17328218193455850539"), - }, - } + priv := parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- +MGECAQACEQDar8EuoZuSosYtE9SeXSyPAgMBAAECEBf7XDET8e6jjTcfO7y/sykC +CQDozXjCjkBzLQIJAPB6MqNbZaQrAghbZTdQoko5LQIIUp9ZiKDdYjMCCCCpqzmX +d8Y7 +-----END RSA TESTING KEY-----`)) testKeyBasics(t, priv) } @@ -113,125 +111,313 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { t.Errorf("private exponent too large") } - if boring.Enabled { - // Cannot call encrypt/decrypt directly. Test via PKCS1v15. - msg := []byte("hi!") - enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg) - if err != nil { - t.Errorf("EncryptPKCS1v15: %v", err) - return - } - dec, err := DecryptPKCS1v15(rand.Reader, priv, enc) - if err != nil { - t.Errorf("DecryptPKCS1v15: %v", err) - return - } - if !bytes.Equal(dec, msg) { - t.Errorf("got:%x want:%x (%+v)", dec, msg, priv) - } + msg := []byte("hi!") + enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg) + if err != nil { + t.Errorf("EncryptPKCS1v15: %v", err) return } - pub := &priv.PublicKey - m := big.NewInt(42) - c := encrypt(new(big.Int), pub, m) - - m2, err := decrypt(nil, priv, c) + dec, err := DecryptPKCS1v15(nil, priv, enc) if err != nil { - t.Errorf("error while decrypting: %s", err) - return + t.Fatalf("DecryptPKCS1v15: %v", err) } - if m.Cmp(m2) != 0 { - t.Errorf("got:%v, want:%v (%+v)", m2, m, priv) + if !bytes.Equal(dec, msg) { + t.Errorf("got:%x want:%x (%+v)", dec, msg, priv) } - m3, err := decrypt(rand.Reader, priv, c) + dec, err = DecryptPKCS1v15(rand.Reader, priv, enc) if err != nil { - t.Errorf("error while decrypting (blind): %s", err) + t.Fatalf("DecryptPKCS1v15: %v", err) } - if m.Cmp(m3) != 0 { - t.Errorf("(blind) got:%v, want:%v (%#v)", m3, m, priv) + if !bytes.Equal(dec, msg) { + t.Errorf("got:%x want:%x (%+v)", dec, msg, priv) } } -func fromBase10(base10 string) *big.Int { - i, ok := new(big.Int).SetString(base10, 10) - if !ok { - panic("bad number: " + base10) +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } + +func parseKey(s string) *PrivateKey { + p, _ := pem.Decode([]byte(s)) + k, err := x509.ParsePKCS1PrivateKey(p.Bytes) + if err != nil { + panic(err) } - return i + return k } -var test2048Key *PrivateKey +var test2048Key = parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- +MIIEnwIBAAKCAQBxY8hCshkKiXCUKydkrtQtQSRke28w4JotocDiVqou4k55DEDJ +akvWbXXDcakV4HA8R2tOGgbxvTjFo8EK470w9O9ipapPUSrRRaBsSOlkaaIs6OYh +4FLwZpqMNBVVEtguVUR/C34Y2pS9kRrHs6q+cGhDZolkWT7nGy5eSEvPDHg0EBq1 +1hu6HmPmI3r0BInONqJg2rcK3U++wk1lnbD3ysCZsKOqRUms3n/IWKeTqXXmz2XK +J2t0NSXwiDmA9q0Gm+w0bXh3lzhtUP4MlzS+lnx9hK5bjzSbCUB5RXwMDG/uNMQq +C4MmA4BPceSfMyAIFjdRLGy/K7gbb2viOYRtAgEDAoIBAEuX2tchZgcGSw1yGkMf +OB4rbZhSSiCVvB5r1ew5xsnsNFCy1ducMo7zo9ehG2Pq9X2E8jQRWfZ+JdkX1gdC +fiCjSkHDxt+LceDZFZ2F8O2bwXNF7sFAN0rvEbLNY44MkB7jgv9c/rs8YykLZy/N +HH71mteZsO2Q1JoSHumFh99cwWHFhLxYh64qFeeH6Gqx6AM2YVBWHgs7OuKOvc8y +zUbf8xftPht1kMwwDR1XySiEYtBtn74JflK3DcT8oxOuCZBuX6sMJHKbVP41zDj+ +FJZBmpAvNfCEYJUr1Hg+DpMLqLUg+D6v5vpliburbk9LxcKFZyyZ9QVe7GoqMLBu +eGsCgYEAummUj4MMKWJC2mv5rj/dt2pj2/B2HtP2RLypai4et1/Ru9nNk8cjMLzC +qXz6/RLuJ7/eD7asFS3y7EqxKxEmW0G8tTHjnzR/3wnpVipuWnwCDGU032HJVd13 +LMe51GH97qLzuDZjMCz+VlbCNdSslMgWWK0XmRnN7Yqxvh6ao2kCgYEAm7fTRBhF +JtKcaJ7d8BQb9l8BNHfjayYOMq5CxoCyxa2pGBv/Mrnxv73Twp9Z/MP0ue5M5nZt +GMovpP5cGdJLQ2w5p4H3opcuWeYW9Yyru2EyCEAI/hD/Td3QVP0ukc19BDuPl5Wg +eIFs218uiVOU4pw3w+Et5B1PZ/F+ZLr5LGUCgYB8RmMKV11w7CyRnVEe1T56Ru09 +Svlp4qQt0xucHr8k6ovSkTO32hd10yxw/fyot0lv1T61JHK4yUydhyDHYMQ81n3O +IUJqIv/qBpuOxvQ8UqwIQ3iU69uOk6TIhSaNlqlJwffQJEIgHf7kOdbOjchjMA7l +yLpmETPzscvUFGcXmwKBgGfP4i1lg283EvBp6Uq4EqQ/ViL6l5zECXce1y8Ady5z +xhASqiHRS9UpN9cU5qiCoyae3e75nhCGym3+6BE23Nede8UBT8G6HuaZZKOzHSeW +IVrVW1QLVN6T4DioybaI/gLSX7pjwFBWSJI/dFuNDexoJS1AyUK+NO/2VEMnUMhD +AoGAOsdn3Prnh/mjC95vraHCLap0bRBSexMdx77ImHgtFUUcSaT8DJHs+NZw1RdM +SZA0J+zVQ8q7B11jIgz5hMz+chedwoRjTL7a8VRTKHFmmBH0zlEuV7L79w6HkRCQ +VRg10GUN6heGLv0aOHbPdobcuVDH4sgOqpT1QnOuce34sQs= +-----END RSA TESTING KEY-----`)) -func init() { - test2048Key = &PrivateKey{ - PublicKey: PublicKey{ - N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"), - E: 3, - }, - D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"), - Primes: []*big.Int{ - fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"), - fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"), - }, - } - test2048Key.Precompute() +var test3072Key = parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- +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 +-----END RSA TESTING KEY-----`)) + +var test4096Key = parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- +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 +-----END RSA TESTING KEY-----`)) + +func BenchmarkDecryptPKCS1v15(b *testing.B) { + b.Run("2048", func(b *testing.B) { benchmarkDecryptPKCS1v15(b, test2048Key) }) + b.Run("3072", func(b *testing.B) { benchmarkDecryptPKCS1v15(b, test3072Key) }) + b.Run("4096", func(b *testing.B) { benchmarkDecryptPKCS1v15(b, test4096Key) }) } -func BenchmarkRSA2048Decrypt(b *testing.B) { - if boring.Enabled { - b.Skip("no raw decrypt in BoringCrypto") +func benchmarkDecryptPKCS1v15(b *testing.B, k *PrivateKey) { + r := bufio.NewReaderSize(rand.Reader, 1<<15) + + m := []byte("Hello Gophers") + c, err := EncryptPKCS1v15(r, &k.PublicKey, m) + if err != nil { + b.Fatal(err) } - b.StopTimer() - - c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313") - - b.StartTimer() - + b.ResetTimer() + var sink byte for i := 0; i < b.N; i++ { - decrypt(nil, test2048Key, c) + p, err := DecryptPKCS1v15(r, k, c) + if err != nil { + b.Fatal(err) + } + if !bytes.Equal(p, m) { + b.Fatalf("unexpected output: %q", p) + } + sink ^= p[0] } } -func BenchmarkRSA2048Sign(b *testing.B) { - b.StopTimer() - hashed := sha256.Sum256([]byte("testing")) - b.StartTimer() +func BenchmarkEncryptPKCS1v15(b *testing.B) { + b.Run("2048", func(b *testing.B) { + r := bufio.NewReaderSize(rand.Reader, 1<<15) + m := []byte("Hello Gophers") - for i := 0; i < b.N; i++ { - SignPKCS1v15(rand.Reader, test2048Key, crypto.SHA256, hashed[:]) - } + var sink byte + for i := 0; i < b.N; i++ { + c, err := EncryptPKCS1v15(r, &test2048Key.PublicKey, m) + if err != nil { + b.Fatal(err) + } + sink ^= c[0] + } + }) } -func Benchmark3PrimeRSA2048Decrypt(b *testing.B) { - if boring.Enabled { - b.Skip("no raw decrypt in BoringCrypto") - } +func BenchmarkDecryptOAEP(b *testing.B) { + b.Run("2048", func(b *testing.B) { + r := bufio.NewReaderSize(rand.Reader, 1<<15) - b.StopTimer() - priv := &PrivateKey{ - PublicKey: PublicKey{ - N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"), - E: 3, - }, - D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"), - Primes: []*big.Int{ - fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"), - fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"), - fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"), - }, - } - priv.Precompute() + m := []byte("Hello Gophers") + c, err := EncryptOAEP(sha256.New(), r, &test2048Key.PublicKey, m, nil) + if err != nil { + b.Fatal(err) + } - c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313") + b.ResetTimer() + var sink byte + for i := 0; i < b.N; i++ { + p, err := DecryptOAEP(sha256.New(), r, test2048Key, c, nil) + if err != nil { + b.Fatal(err) + } + if !bytes.Equal(p, m) { + b.Fatalf("unexpected output: %q", p) + } + sink ^= p[0] + } + }) +} - b.StartTimer() +func BenchmarkEncryptOAEP(b *testing.B) { + b.Run("2048", func(b *testing.B) { + r := bufio.NewReaderSize(rand.Reader, 1<<15) + m := []byte("Hello Gophers") - for i := 0; i < b.N; i++ { - decrypt(nil, priv, c) - } + var sink byte + for i := 0; i < b.N; i++ { + c, err := EncryptOAEP(sha256.New(), r, &test2048Key.PublicKey, m, nil) + if err != nil { + b.Fatal(err) + } + sink ^= c[0] + } + }) +} + +func BenchmarkSignPKCS1v15(b *testing.B) { + b.Run("2048", func(b *testing.B) { + hashed := sha256.Sum256([]byte("testing")) + + var sink byte + b.ResetTimer() + for i := 0; i < b.N; i++ { + s, err := SignPKCS1v15(rand.Reader, test2048Key, crypto.SHA256, hashed[:]) + if err != nil { + b.Fatal(err) + } + sink ^= s[0] + } + }) +} + +func BenchmarkVerifyPKCS1v15(b *testing.B) { + b.Run("2048", func(b *testing.B) { + hashed := sha256.Sum256([]byte("testing")) + s, err := SignPKCS1v15(rand.Reader, test2048Key, crypto.SHA256, hashed[:]) + if err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + err := VerifyPKCS1v15(&test2048Key.PublicKey, crypto.SHA256, hashed[:], s) + if err != nil { + b.Fatal(err) + } + } + }) +} + +func BenchmarkSignPSS(b *testing.B) { + b.Run("2048", func(b *testing.B) { + hashed := sha256.Sum256([]byte("testing")) + + var sink byte + b.ResetTimer() + for i := 0; i < b.N; i++ { + s, err := SignPSS(rand.Reader, test2048Key, crypto.SHA256, hashed[:], nil) + if err != nil { + b.Fatal(err) + } + sink ^= s[0] + } + }) +} + +func BenchmarkVerifyPSS(b *testing.B) { + b.Run("2048", func(b *testing.B) { + hashed := sha256.Sum256([]byte("testing")) + s, err := SignPSS(rand.Reader, test2048Key, crypto.SHA256, hashed[:], nil) + if err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + err := VerifyPSS(&test2048Key.PublicKey, crypto.SHA256, hashed[:], s, nil) + if err != nil { + b.Fatal(err) + } + } + }) } type testEncryptOAEPMessage struct {