OLD | NEW |
(Empty) | |
| 1 # -*- coding: utf-8 -*- |
| 2 # |
| 3 # Cipher/PKCS1-v1_5.py : PKCS#1 v1.5 |
| 4 # |
| 5 # =================================================================== |
| 6 # The contents of this file are dedicated to the public domain. To |
| 7 # the extent that dedication to the public domain is not available, |
| 8 # everyone is granted a worldwide, perpetual, royalty-free, |
| 9 # non-exclusive license to exercise all rights associated with the |
| 10 # contents of this file for any purpose whatsoever. |
| 11 # No rights are reserved. |
| 12 # |
| 13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 14 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 15 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 16 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 17 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 18 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 19 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 20 # SOFTWARE. |
| 21 # =================================================================== |
| 22 |
| 23 """RSA encryption protocol according to PKCS#1 v1.5 |
| 24 |
| 25 See RFC3447__ or the `original RSA Labs specification`__ . |
| 26 |
| 27 This scheme is more properly called ``RSAES-PKCS1-v1_5``. |
| 28 |
| 29 **If you are designing a new protocol, consider using the more robust PKCS#1 OAE
P.** |
| 30 |
| 31 As an example, a sender may encrypt a message in this way: |
| 32 |
| 33 >>> from Crypto.Cipher import PKCS1_v1_5 |
| 34 >>> from Crypto.PublicKey import RSA |
| 35 >>> from Crypto.Hash import SHA |
| 36 >>> |
| 37 >>> message = 'To be encrypted' |
| 38 >>> h = SHA.new(message) |
| 39 >>> |
| 40 >>> key = RSA.importKey(open('pubkey.der').read()) |
| 41 >>> cipher = PKCS1_v1_5.new(key) |
| 42 >>> ciphertext = cipher.encrypt(message+h.digest()) |
| 43 |
| 44 At the receiver side, decryption can be done using the private part of |
| 45 the RSA key: |
| 46 |
| 47 >>> From Crypto.Hash import SHA |
| 48 >>> from Crypto import Random |
| 49 >>> |
| 50 >>> key = RSA.importKey(open('privkey.der').read()) |
| 51 >>> |
| 52 >>> dsize = SHA.digest_size |
| 53 >>> sentinel = Random.new().read(15+dsize) # Let's assume that aver
age data length is 15 |
| 54 >>> |
| 55 >>> cipher = PKCS1_v1_5.new(key) |
| 56 >>> message = cipher.decrypt(ciphertext, sentinel) |
| 57 >>> |
| 58 >>> digest = SHA.new(message[:-dsize]).digest() |
| 59 >>> if digest==message[-dsize:]: # Note how we DO NOT loo
k for the sentinel |
| 60 >>> print "Encryption was correct." |
| 61 >>> else: |
| 62 >>> print "Encryption was not correct." |
| 63 |
| 64 :undocumented: __revision__, __package__ |
| 65 |
| 66 .. __: http://www.ietf.org/rfc/rfc3447.txt |
| 67 .. __: http://www.rsa.com/rsalabs/node.asp?id=2125. |
| 68 """ |
| 69 |
| 70 __revision__ = "$Id$" |
| 71 __all__ = [ 'new', 'PKCS115_Cipher' ] |
| 72 |
| 73 from Crypto.Util.number import ceil_div |
| 74 from Crypto.Util.py3compat import * |
| 75 import Crypto.Util.number |
| 76 |
| 77 class PKCS115_Cipher: |
| 78 """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption.""" |
| 79 |
| 80 def __init__(self, key): |
| 81 """Initialize this PKCS#1 v1.5 cipher object. |
| 82 |
| 83 :Parameters: |
| 84 key : an RSA key object |
| 85 If a private half is given, both encryption and decryption are possibl
e. |
| 86 If a public half is given, only encryption is possible. |
| 87 """ |
| 88 self._key = key |
| 89 |
| 90 def can_encrypt(self): |
| 91 """Return True if this cipher object can be used for encryption.""" |
| 92 return self._key.can_encrypt() |
| 93 |
| 94 def can_decrypt(self): |
| 95 """Return True if this cipher object can be used for decryption.""" |
| 96 return self._key.can_decrypt() |
| 97 |
| 98 def encrypt(self, message): |
| 99 """Produce the PKCS#1 v1.5 encryption of a message. |
| 100 |
| 101 This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and is specified in |
| 102 section 7.2.1 of RFC3447. |
| 103 For a complete example see `Crypto.Cipher.PKCS1_v1_5`. |
| 104 |
| 105 :Parameters: |
| 106 message : byte string |
| 107 The message to encrypt, also known as plaintext. It can be of |
| 108 variable length, but not longer than the RSA modulus (in bytes)
minus 11. |
| 109 |
| 110 :Return: A byte string, the ciphertext in which the message is encrypted
. |
| 111 It is as long as the RSA modulus (in bytes). |
| 112 :Raise ValueError: |
| 113 If the RSA key length is not sufficiently long to deal with the give
n |
| 114 message. |
| 115 |
| 116 """ |
| 117 # TODO: Verify the key is RSA |
| 118 |
| 119 randFunc = self._key._randfunc |
| 120 |
| 121 # See 7.2.1 in RFC3447 |
| 122 modBits = Crypto.Util.number.size(self._key.n) |
| 123 k = ceil_div(modBits,8) # Convert from bits to bytes |
| 124 mLen = len(message) |
| 125 |
| 126 # Step 1 |
| 127 if mLen > k-11: |
| 128 raise ValueError("Plaintext is too long.") |
| 129 # Step 2a |
| 130 class nonZeroRandByte: |
| 131 def __init__(self, rf): self.rf=rf |
| 132 def __call__(self, c): |
| 133 while bord(c)==0x00: c=self.rf(1)[0] |
| 134 return c |
| 135 ps = tobytes(map(nonZeroRandByte(randFunc), randFunc(k-mLen-3))) |
| 136 # Step 2b |
| 137 em = b('\x00\x02') + ps + bchr(0x00) + message |
| 138 # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP) |
| 139 m = self._key.encrypt(em, 0)[0] |
| 140 # Complete step 3c (I2OSP) |
| 141 c = bchr(0x00)*(k-len(m)) + m |
| 142 return c |
| 143 |
| 144 def decrypt(self, ct, sentinel): |
| 145 """Decrypt a PKCS#1 v1.5 ciphertext. |
| 146 |
| 147 This function is named ``RSAES-PKCS1-V1_5-DECRYPT``, and is specified in |
| 148 section 7.2.2 of RFC3447. |
| 149 For a complete example see `Crypto.Cipher.PKCS1_v1_5`. |
| 150 |
| 151 :Parameters: |
| 152 ct : byte string |
| 153 The ciphertext that contains the message to recover. |
| 154 sentinel : any type |
| 155 The object to return to indicate that an error was detected duri
ng decryption. |
| 156 |
| 157 :Return: A byte string. It is either the original message or the ``senti
nel`` (in case of an error). |
| 158 :Raise ValueError: |
| 159 If the ciphertext length is incorrect |
| 160 :Raise TypeError: |
| 161 If the RSA key has no private half. |
| 162 |
| 163 :attention: |
| 164 You should **never** let the party who submitted the ciphertext know
that |
| 165 this function returned the ``sentinel`` value. |
| 166 Armed with such knowledge (for a fair amount of carefully crafted bu
t invalid ciphertexts), |
| 167 an attacker is able to recontruct the plaintext of any other encrypt
ion that were carried out |
| 168 with the same RSA public key (see `Bleichenbacher's`__ attack). |
| 169 |
| 170 In general, it should not be possible for the other party to disting
uish |
| 171 whether processing at the server side failed because the value retur
ned |
| 172 was a ``sentinel`` as opposed to a random, invalid message. |
| 173 |
| 174 In fact, the second option is not that unlikely: encryption done acc
ording to PKCS#1 v1.5 |
| 175 embeds no good integrity check. There is roughly one chance |
| 176 in 2^16 for a random ciphertext to be returned as a valid message |
| 177 (although random looking). |
| 178 |
| 179 It is therefore advisabled to: |
| 180 |
| 181 1. Select as ``sentinel`` a value that resembles a plausable random,
invalid message. |
| 182 2. Not report back an error as soon as you detect a ``sentinel`` val
ue. |
| 183 Put differently, you should not explicitly check if the returned
value is the ``sentinel`` or not. |
| 184 3. Cover all possible errors with a single, generic error indicator. |
| 185 4. Embed into the definition of ``message`` (at the protocol level)
a digest (e.g. ``SHA-1``). |
| 186 It is recommended for it to be the rightmost part ``message``. |
| 187 5. Where possible, monitor the number of errors due to ciphertexts o
riginating from the same party, |
| 188 and slow down the rate of the requests from such party (or even b
lacklist it altogether). |
| 189 |
| 190 **If you are designing a new protocol, consider using the more robus
t PKCS#1 OAEP.** |
| 191 |
| 192 .. __: http://www.bell-labs.com/user/bleichen/papers/pkcs.ps |
| 193 |
| 194 """ |
| 195 |
| 196 # TODO: Verify the key is RSA |
| 197 |
| 198 # See 7.2.1 in RFC3447 |
| 199 modBits = Crypto.Util.number.size(self._key.n) |
| 200 k = ceil_div(modBits,8) # Convert from bits to bytes |
| 201 |
| 202 # Step 1 |
| 203 if len(ct) != k: |
| 204 raise ValueError("Ciphertext with incorrect length.") |
| 205 # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP) |
| 206 m = self._key.decrypt(ct) |
| 207 # Complete step 2c (I2OSP) |
| 208 em = bchr(0x00)*(k-len(m)) + m |
| 209 # Step 3 |
| 210 sep = em.find(bchr(0x00),2) |
| 211 if not em.startswith(b('\x00\x02')) or sep<10: |
| 212 return sentinel |
| 213 # Step 4 |
| 214 return em[sep+1:] |
| 215 |
| 216 def new(key): |
| 217 """Return a cipher object `PKCS115_Cipher` that can be used to perform PKCS#
1 v1.5 encryption or decryption. |
| 218 |
| 219 :Parameters: |
| 220 key : RSA key object |
| 221 The key to use to encrypt or decrypt the message. This is a `Crypto.Public
Key.RSA` object. |
| 222 Decryption is only possible if *key* is a private RSA key. |
| 223 |
| 224 """ |
| 225 return PKCS115_Cipher(key) |
| 226 |
OLD | NEW |