github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/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 // The PS padding must be at least 8 bytes long, and it starts two 128 // bytes into em. 129 validPS := subtle.ConstantTimeLessOrEq(2+8, index) 130 131 valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS 132 msg = em[index+1:] 133 return 134 } 135 136 // nonZeroRandomBytes fills the given slice with non-zero random octets. 137 func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { 138 _, err = io.ReadFull(rand, s) 139 if err != nil { 140 return 141 } 142 143 for i := 0; i < len(s); i++ { 144 for s[i] == 0 { 145 _, err = io.ReadFull(rand, s[i:i+1]) 146 if err != nil { 147 return 148 } 149 // In tests, the PRNG may return all zeros so we do 150 // this to break the loop. 151 s[i] ^= 0x42 152 } 153 } 154 155 return 156 } 157 158 // These are ASN1 DER structures: 159 // DigestInfo ::= SEQUENCE { 160 // digestAlgorithm AlgorithmIdentifier, 161 // digest OCTET STRING 162 // } 163 // For performance, we don't use the generic ASN1 encoder. Rather, we 164 // precompute a prefix of the digest value that makes a valid ASN1 DER string 165 // with the correct contents. 166 var hashPrefixes = map[crypto.Hash][]byte{ 167 crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}, 168 crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}, 169 crypto.SHA224: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c}, 170 crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}, 171 crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}, 172 crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}, 173 crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix. 174 crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14}, 175 } 176 177 // SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. 178 // Note that hashed must be the result of hashing the input message using the 179 // given hash function. 180 func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error) { 181 hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) 182 if err != nil { 183 return 184 } 185 186 tLen := len(prefix) + hashLen 187 k := (priv.N.BitLen() + 7) / 8 188 if k < tLen+11 { 189 return nil, ErrMessageTooLong 190 } 191 192 // EM = 0x00 || 0x01 || PS || 0x00 || T 193 em := make([]byte, k) 194 em[1] = 1 195 for i := 2; i < k-tLen-1; i++ { 196 em[i] = 0xff 197 } 198 copy(em[k-tLen:k-hashLen], prefix) 199 copy(em[k-hashLen:k], hashed) 200 201 m := new(big.Int).SetBytes(em) 202 c, err := decrypt(rand, priv, m) 203 if err != nil { 204 return 205 } 206 207 copyWithLeftPad(em, c.Bytes()) 208 s = em 209 return 210 } 211 212 // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature. 213 // hashed is the result of hashing the input message using the given hash 214 // function and sig is the signature. A valid signature is indicated by 215 // returning a nil error. 216 func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error) { 217 hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) 218 if err != nil { 219 return 220 } 221 222 tLen := len(prefix) + hashLen 223 k := (pub.N.BitLen() + 7) / 8 224 if k < tLen+11 { 225 err = ErrVerification 226 return 227 } 228 229 c := new(big.Int).SetBytes(sig) 230 m := encrypt(new(big.Int), pub, c) 231 em := leftPad(m.Bytes(), k) 232 // EM = 0x00 || 0x01 || PS || 0x00 || T 233 234 ok := subtle.ConstantTimeByteEq(em[0], 0) 235 ok &= subtle.ConstantTimeByteEq(em[1], 1) 236 ok &= subtle.ConstantTimeCompare(em[k-hashLen:k], hashed) 237 ok &= subtle.ConstantTimeCompare(em[k-tLen:k-hashLen], prefix) 238 ok &= subtle.ConstantTimeByteEq(em[k-tLen-1], 0) 239 240 for i := 2; i < k-tLen-1; i++ { 241 ok &= subtle.ConstantTimeByteEq(em[i], 0xff) 242 } 243 244 if ok != 1 { 245 return ErrVerification 246 } 247 248 return nil 249 } 250 251 func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) { 252 hashLen = hash.Size() 253 if inLen != hashLen { 254 return 0, nil, errors.New("crypto/rsa: input must be hashed message") 255 } 256 prefix, ok := hashPrefixes[hash] 257 if !ok { 258 return 0, nil, errors.New("crypto/rsa: unsupported hash function") 259 } 260 return 261 } 262 263 // copyWithLeftPad copies src to the end of dest, padding with zero bytes as 264 // needed. 265 func copyWithLeftPad(dest, src []byte) { 266 numPaddingBytes := len(dest) - len(src) 267 for i := 0; i < numPaddingBytes; i++ { 268 dest[i] = 0 269 } 270 copy(dest[numPaddingBytes:], src) 271 }