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