Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: third_party/google-endpoints/Crypto/Cipher/PKCS1_v1_5.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW
« no previous file with comments | « third_party/google-endpoints/Crypto/Cipher/PKCS1_OAEP.py ('k') | third_party/google-endpoints/Crypto/Cipher/XOR.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698