Commit 40ac3690 authored by Adam Langley's avatar Adam Langley

crypto/rsa: check CRT result.

This change adds a check after computing an RSA signature that the
signature is correct. This prevents an error in the CRT computation from
leaking the private key. See references in the linked bug.

benchmark                  old ns/op     new ns/op     delta
BenchmarkRSA2048Sign-3     5713305       6225215       +8.96%

Fixes #12453

Change-Id: I1f24e0b542f7c9a3f7e7ad4e971db3dc440ed3c1
Reviewed-on: https://go-review.googlesource.com/17862Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: 's avatarRobert Griesemer <gri@golang.org>
Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent f33f9b2c
...@@ -223,7 +223,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b ...@@ -223,7 +223,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
copy(em[k-hashLen:k], hashed) copy(em[k-hashLen:k], hashed)
m := new(big.Int).SetBytes(em) m := new(big.Int).SetBytes(em)
c, err := decrypt(rand, priv, m) c, err := decryptAndCheck(rand, priv, m)
if err != nil { if err != nil {
return return
} }
......
...@@ -198,7 +198,7 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, ...@@ -198,7 +198,7 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed,
return return
} }
m := new(big.Int).SetBytes(em) m := new(big.Int).SetBytes(em)
c, err := decrypt(rand, priv, m) c, err := decryptAndCheck(rand, priv, m)
if err != nil { if err != nil {
return return
} }
......
...@@ -506,6 +506,21 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er ...@@ -506,6 +506,21 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er
return return
} }
func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
m, err = decrypt(random, priv, c)
if err != nil {
return nil, err
}
// In order to defend against errors in the CRT computation, m^e is
// calculated, which should match the original ciphertext.
check := encrypt(new(big.Int), &priv.PublicKey, m)
if c.Cmp(check) != 0 {
return nil, errors.New("rsa: internal error")
}
return m, nil
}
// DecryptOAEP decrypts ciphertext using RSA-OAEP. // DecryptOAEP decrypts ciphertext using RSA-OAEP.
// If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks. // If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) { func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
......
...@@ -6,8 +6,10 @@ package rsa ...@@ -6,8 +6,10 @@ package rsa
import ( import (
"bytes" "bytes"
"crypto"
"crypto/rand" "crypto/rand"
"crypto/sha1" "crypto/sha1"
"crypto/sha256"
"math/big" "math/big"
"testing" "testing"
) )
...@@ -127,9 +129,10 @@ func fromBase10(base10 string) *big.Int { ...@@ -127,9 +129,10 @@ func fromBase10(base10 string) *big.Int {
return i return i
} }
func BenchmarkRSA2048Decrypt(b *testing.B) { var test2048Key *PrivateKey
b.StopTimer()
priv := &PrivateKey{ func init() {
test2048Key = &PrivateKey{
PublicKey: PublicKey{ PublicKey: PublicKey{
N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"), N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"),
E: 3, E: 3,
...@@ -140,14 +143,28 @@ func BenchmarkRSA2048Decrypt(b *testing.B) { ...@@ -140,14 +143,28 @@ func BenchmarkRSA2048Decrypt(b *testing.B) {
fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"), fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
}, },
} }
priv.Precompute() test2048Key.Precompute()
}
func BenchmarkRSA2048Decrypt(b *testing.B) {
b.StopTimer()
c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313") c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
decrypt(nil, priv, c) decrypt(nil, test2048Key, c)
}
}
func BenchmarkRSA2048Sign(b *testing.B) {
b.StopTimer()
hashed := sha256.Sum256([]byte("testing"))
b.StartTimer()
for i := 0; i < b.N; i++ {
SignPKCS1v15(rand.Reader, test2048Key, crypto.SHA256, hashed[:])
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment