Home | History | Annotate | Download | only in rsa
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package rsa
      6 
      7 import (
      8 	"crypto"
      9 	"crypto/subtle"
     10 	"errors"
     11 	"io"
     12 	"math/big"
     13 )
     14 
     15 // This file implements encryption and decryption using PKCS#1 v1.5 padding.
     16 
     17 // PKCS1v15DecrypterOpts is for passing options to PKCS#1 v1.5 decryption using
     18 // the crypto.Decrypter interface.
     19 type PKCS1v15DecryptOptions struct {
     20 	// SessionKeyLen is the length of the session key that is being
     21 	// decrypted. If not zero, then a padding error during decryption will
     22 	// cause a random plaintext of this length to be returned rather than
     23 	// an error. These alternatives happen in constant time.
     24 	SessionKeyLen int
     25 }
     26 
     27 // EncryptPKCS1v15 encrypts the given message with RSA and the padding scheme from PKCS#1 v1.5.
     28 // The message must be no longer than the length of the public modulus minus 11 bytes.
     29 // WARNING: use of this function to encrypt plaintexts other than session keys
     30 // is dangerous. Use RSA OAEP in new protocols.
     31 func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) {
     32 	if err := checkPub(pub); err != nil {
     33 		return nil, err
     34 	}
     35 	k := (pub.N.BitLen() + 7) / 8
     36 	if len(msg) > k-11 {
     37 		err = ErrMessageTooLong
     38 		return
     39 	}
     40 
     41 	// EM = 0x00 || 0x02 || PS || 0x00 || M
     42 	em := make([]byte, k)
     43 	em[1] = 2
     44 	ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
     45 	err = nonZeroRandomBytes(ps, rand)
     46 	if err != nil {
     47 		return
     48 	}
     49 	em[len(em)-len(msg)-1] = 0
     50 	copy(mm, msg)
     51 
     52 	m := new(big.Int).SetBytes(em)
     53 	c := encrypt(new(big.Int), pub, m)
     54 
     55 	copyWithLeftPad(em, c.Bytes())
     56 	out = em
     57 	return
     58 }
     59 
     60 // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
     61 // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
     62 func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
     63 	if err := checkPub(&priv.PublicKey); err != nil {
     64 		return nil, err
     65 	}
     66 	valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext)
     67 	if err != nil {
     68 		return
     69 	}
     70 	if valid == 0 {
     71 		return nil, ErrDecryption
     72 	}
     73 	out = out[index:]
     74 	return
     75 }
     76 
     77 // DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5.
     78 // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
     79 // It returns an error if the ciphertext is the wrong length or if the
     80 // ciphertext is greater than the public modulus. Otherwise, no error is
     81 // returned. If the padding is valid, the resulting plaintext message is copied
     82 // into key. Otherwise, key is unchanged. These alternatives occur in constant
     83 // time. It is intended that the user of this function generate a random
     84 // session key beforehand and continue the protocol with the resulting value.
     85 // This will remove any possibility that an attacker can learn any information
     86 // about the plaintext.
     87 // See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA
     88 // Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
     89 // (Crypto '98).
     90 func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
     91 	if err := checkPub(&priv.PublicKey); err != nil {
     92 		return err
     93 	}
     94 	k := (priv.N.BitLen() + 7) / 8
     95 	if k-(len(key)+3+8) < 0 {
     96 		return ErrDecryption
     97 	}
     98 
     99 	valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext)
    100 	if err != nil {
    101 		return
    102 	}
    103 
    104 	if len(em) != k {
    105 		// This should be impossible because decryptPKCS1v15 always
    106 		// returns the full slice.
    107 		return ErrDecryption
    108 	}
    109 
    110 	valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key)))
    111 	subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):])
    112 	return
    113 }
    114 
    115 // decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if
    116 // rand is not nil. It returns one or zero in valid that indicates whether the
    117 // plaintext was correctly structured. In either case, the plaintext is
    118 // returned in em so that it may be read independently of whether it was valid
    119 // in order to maintain constant memory access patterns. If the plaintext was
    120 // valid then index contains the index of the original message in em.
    121 func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
    122 	k := (priv.N.BitLen() + 7) / 8
    123 	if k < 11 {
    124 		err = ErrDecryption
    125 		return
    126 	}
    127 
    128 	c := new(big.Int).SetBytes(ciphertext)
    129 	m, err := decrypt(rand, priv, c)
    130 	if err != nil {
    131 		return
    132 	}
    133 
    134 	em = leftPad(m.Bytes(), k)
    135 	firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
    136 	secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
    137 
    138 	// The remainder of the plaintext must be a string of non-zero random
    139 	// octets, followed by a 0, followed by the message.
    140 	//   lookingForIndex: 1 iff we are still looking for the zero.
    141 	//   index: the offset of the first zero byte.
    142 	lookingForIndex := 1
    143 
    144 	for i := 2; i < len(em); i++ {
    145 		equals0 := subtle.ConstantTimeByteEq(em[i], 0)
    146 		index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
    147 		lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
    148 	}
    149 
    150 	// The PS padding must be at least 8 bytes long, and it starts two
    151 	// bytes into em.
    152 	validPS := subtle.ConstantTimeLessOrEq(2+8, index)
    153 
    154 	valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS
    155 	index = subtle.ConstantTimeSelect(valid, index+1, 0)
    156 	return valid, em, index, nil
    157 }
    158 
    159 // nonZeroRandomBytes fills the given slice with non-zero random octets.
    160 func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
    161 	_, err = io.ReadFull(rand, s)
    162 	if err != nil {
    163 		return
    164 	}
    165 
    166 	for i := 0; i < len(s); i++ {
    167 		for s[i] == 0 {
    168 			_, err = io.ReadFull(rand, s[i:i+1])
    169 			if err != nil {
    170 				return
    171 			}
    172 			// In tests, the PRNG may return all zeros so we do
    173 			// this to break the loop.
    174 			s[i] ^= 0x42
    175 		}
    176 	}
    177 
    178 	return
    179 }
    180 
    181 // These are ASN1 DER structures:
    182 //   DigestInfo ::= SEQUENCE {
    183 //     digestAlgorithm AlgorithmIdentifier,
    184 //     digest OCTET STRING
    185 //   }
    186 // For performance, we don't use the generic ASN1 encoder. Rather, we
    187 // precompute a prefix of the digest value that makes a valid ASN1 DER string
    188 // with the correct contents.
    189 var hashPrefixes = map[crypto.Hash][]byte{
    190 	crypto.MD5:       {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
    191 	crypto.SHA1:      {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
    192 	crypto.SHA224:    {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
    193 	crypto.SHA256:    {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
    194 	crypto.SHA384:    {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
    195 	crypto.SHA512:    {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
    196 	crypto.MD5SHA1:   {}, // A special TLS case which doesn't use an ASN1 prefix.
    197 	crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
    198 }
    199 
    200 // SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5.
    201 // Note that hashed must be the result of hashing the input message using the
    202 // given hash function. If hash is zero, hashed is signed directly. This isn't
    203 // advisable except for interoperability.
    204 func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error) {
    205 	hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
    206 	if err != nil {
    207 		return
    208 	}
    209 
    210 	tLen := len(prefix) + hashLen
    211 	k := (priv.N.BitLen() + 7) / 8
    212 	if k < tLen+11 {
    213 		return nil, ErrMessageTooLong
    214 	}
    215 
    216 	// EM = 0x00 || 0x01 || PS || 0x00 || T
    217 	em := make([]byte, k)
    218 	em[1] = 1
    219 	for i := 2; i < k-tLen-1; i++ {
    220 		em[i] = 0xff
    221 	}
    222 	copy(em[k-tLen:k-hashLen], prefix)
    223 	copy(em[k-hashLen:k], hashed)
    224 
    225 	m := new(big.Int).SetBytes(em)
    226 	c, err := decrypt(rand, priv, m)
    227 	if err != nil {
    228 		return
    229 	}
    230 
    231 	copyWithLeftPad(em, c.Bytes())
    232 	s = em
    233 	return
    234 }
    235 
    236 // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
    237 // hashed is the result of hashing the input message using the given hash
    238 // function and sig is the signature. A valid signature is indicated by
    239 // returning a nil error. If hash is zero then hashed is used directly. This
    240 // isn't advisable except for interoperability.
    241 func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error) {
    242 	hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
    243 	if err != nil {
    244 		return
    245 	}
    246 
    247 	tLen := len(prefix) + hashLen
    248 	k := (pub.N.BitLen() + 7) / 8
    249 	if k < tLen+11 {
    250 		err = ErrVerification
    251 		return
    252 	}
    253 
    254 	c := new(big.Int).SetBytes(sig)
    255 	m := encrypt(new(big.Int), pub, c)
    256 	em := leftPad(m.Bytes(), k)
    257 	// EM = 0x00 || 0x01 || PS || 0x00 || T
    258 
    259 	ok := subtle.ConstantTimeByteEq(em[0], 0)
    260 	ok &= subtle.ConstantTimeByteEq(em[1], 1)
    261 	ok &= subtle.ConstantTimeCompare(em[k-hashLen:k], hashed)
    262 	ok &= subtle.ConstantTimeCompare(em[k-tLen:k-hashLen], prefix)
    263 	ok &= subtle.ConstantTimeByteEq(em[k-tLen-1], 0)
    264 
    265 	for i := 2; i < k-tLen-1; i++ {
    266 		ok &= subtle.ConstantTimeByteEq(em[i], 0xff)
    267 	}
    268 
    269 	if ok != 1 {
    270 		return ErrVerification
    271 	}
    272 
    273 	return nil
    274 }
    275 
    276 func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
    277 	// Special case: crypto.Hash(0) is used to indicate that the data is
    278 	// signed directly.
    279 	if hash == 0 {
    280 		return inLen, nil, nil
    281 	}
    282 
    283 	hashLen = hash.Size()
    284 	if inLen != hashLen {
    285 		return 0, nil, errors.New("crypto/rsa: input must be hashed message")
    286 	}
    287 	prefix, ok := hashPrefixes[hash]
    288 	if !ok {
    289 		return 0, nil, errors.New("crypto/rsa: unsupported hash function")
    290 	}
    291 	return
    292 }
    293 
    294 // copyWithLeftPad copies src to the end of dest, padding with zero bytes as
    295 // needed.
    296 func copyWithLeftPad(dest, src []byte) {
    297 	numPaddingBytes := len(dest) - len(src)
    298 	for i := 0; i < numPaddingBytes; i++ {
    299 		dest[i] = 0
    300 	}
    301 	copy(dest[numPaddingBytes:], src)
    302 }
    303