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

Side by Side Diff: third_party/google-endpoints/Crypto/Cipher/PKCS1_OAEP.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_OAEP.py : PKCS#1 OAEP
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 OAEP
24
25 See RFC3447__ or the `original RSA Labs specification`__ .
26
27 This scheme is more properly called ``RSAES-OAEP``.
28
29 As an example, a sender may encrypt a message in this way:
30
31 >>> from Crypto.Cipher import PKCS1_OAEP
32 >>> from Crypto.PublicKey import RSA
33 >>>
34 >>> message = 'To be encrypted'
35 >>> key = RSA.importKey(open('pubkey.der').read())
36 >>> cipher = PKCS1_OAEP.new(key)
37 >>> ciphertext = cipher.encrypt(message)
38
39 At the receiver side, decryption can be done using the private part of
40 the RSA key:
41
42 >>> key = RSA.importKey(open('privkey.der').read())
43 >>> cipher = PKCS1_OAP.new(key)
44 >>> message = cipher.decrypt(ciphertext)
45
46 :undocumented: __revision__, __package__
47
48 .. __: http://www.ietf.org/rfc/rfc3447.txt
49 .. __: http://www.rsa.com/rsalabs/node.asp?id=2125.
50 """
51
52 from __future__ import nested_scopes
53
54 __revision__ = "$Id$"
55 __all__ = [ 'new', 'PKCS1OAEP_Cipher' ]
56
57 import Crypto.Signature.PKCS1_PSS
58 import Crypto.Hash.SHA
59
60 from Crypto.Util.py3compat import *
61 import Crypto.Util.number
62 from Crypto.Util.number import ceil_div
63 from Crypto.Util.strxor import strxor
64
65 class PKCS1OAEP_Cipher:
66 """This cipher can perform PKCS#1 v1.5 OAEP encryption or decryption."""
67
68 def __init__(self, key, hashAlgo, mgfunc, label):
69 """Initialize this PKCS#1 OAEP cipher object.
70
71 :Parameters:
72 key : an RSA key object
73 If a private half is given, both encryption and decryption are possibl e.
74 If a public half is given, only encryption is possible.
75 hashAlgo : hash object
76 The hash function to use. This can be a module under `Crypto.Has h`
77 or an existing hash object created from any of such modules. If not specified,
78 `Crypto.Hash.SHA` (that is, SHA-1) is used.
79 mgfunc : callable
80 A mask generation function that accepts two parameters: a string to
81 use as seed, and the lenth of the mask to generate, in bytes.
82 If not specified, the standard MGF1 is used (a safe choice).
83 label : string
84 A label to apply to this particular encryption. If not specified ,
85 an empty string is used. Specifying a label does not improve
86 security.
87
88 :attention: Modify the mask generation function only if you know what yo u are doing.
89 Sender and receiver must use the same one.
90 """
91 self._key = key
92
93 if hashAlgo:
94 self._hashObj = hashAlgo
95 else:
96 self._hashObj = Crypto.Hash.SHA
97
98 if mgfunc:
99 self._mgf = mgfunc
100 else:
101 self._mgf = lambda x,y: Crypto.Signature.PKCS1_PSS.MGF1(x,y,self._ha shObj)
102
103 self._label = label
104
105 def can_encrypt(self):
106 """Return True/1 if this cipher object can be used for encryption."""
107 return self._key.can_encrypt()
108
109 def can_decrypt(self):
110 """Return True/1 if this cipher object can be used for decryption."""
111 return self._key.can_decrypt()
112
113 def encrypt(self, message):
114 """Produce the PKCS#1 OAEP encryption of a message.
115
116 This function is named ``RSAES-OAEP-ENCRYPT``, and is specified in
117 section 7.1.1 of RFC3447.
118
119 :Parameters:
120 message : string
121 The message to encrypt, also known as plaintext. It can be of
122 variable length, but not longer than the RSA modulus (in bytes)
123 minus 2, minus twice the hash output size.
124
125 :Return: A string, the ciphertext in which the message is encrypted.
126 It is as long as the RSA modulus (in bytes).
127 :Raise ValueError:
128 If the RSA key length is not sufficiently long to deal with the give n
129 message.
130 """
131 # TODO: Verify the key is RSA
132
133 randFunc = self._key._randfunc
134
135 # See 7.1.1 in RFC3447
136 modBits = Crypto.Util.number.size(self._key.n)
137 k = ceil_div(modBits,8) # Convert from bits to bytes
138 hLen = self._hashObj.digest_size
139 mLen = len(message)
140
141 # Step 1b
142 ps_len = k-mLen-2*hLen-2
143 if ps_len<0:
144 raise ValueError("Plaintext is too long.")
145 # Step 2a
146 lHash = self._hashObj.new(self._label).digest()
147 # Step 2b
148 ps = bchr(0x00)*ps_len
149 # Step 2c
150 db = lHash + ps + bchr(0x01) + message
151 # Step 2d
152 ros = randFunc(hLen)
153 # Step 2e
154 dbMask = self._mgf(ros, k-hLen-1)
155 # Step 2f
156 maskedDB = strxor(db, dbMask)
157 # Step 2g
158 seedMask = self._mgf(maskedDB, hLen)
159 # Step 2h
160 maskedSeed = strxor(ros, seedMask)
161 # Step 2i
162 em = bchr(0x00) + maskedSeed + maskedDB
163 # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP)
164 m = self._key.encrypt(em, 0)[0]
165 # Complete step 3c (I2OSP)
166 c = bchr(0x00)*(k-len(m)) + m
167 return c
168
169 def decrypt(self, ct):
170 """Decrypt a PKCS#1 OAEP ciphertext.
171
172 This function is named ``RSAES-OAEP-DECRYPT``, and is specified in
173 section 7.1.2 of RFC3447.
174
175 :Parameters:
176 ct : string
177 The ciphertext that contains the message to recover.
178
179 :Return: A string, the original message.
180 :Raise ValueError:
181 If the ciphertext length is incorrect, or if the decryption does not
182 succeed.
183 :Raise TypeError:
184 If the RSA key has no private half.
185 """
186 # TODO: Verify the key is RSA
187
188 # See 7.1.2 in RFC3447
189 modBits = Crypto.Util.number.size(self._key.n)
190 k = ceil_div(modBits,8) # Convert from bits to bytes
191 hLen = self._hashObj.digest_size
192
193 # Step 1b and 1c
194 if len(ct) != k or k<hLen+2:
195 raise ValueError("Ciphertext with incorrect length.")
196 # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP)
197 m = self._key.decrypt(ct)
198 # Complete step 2c (I2OSP)
199 em = bchr(0x00)*(k-len(m)) + m
200 # Step 3a
201 lHash = self._hashObj.new(self._label).digest()
202 # Step 3b
203 y = em[0]
204 # y must be 0, but we MUST NOT check it here in order not to
205 # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
206 maskedSeed = em[1:hLen+1]
207 maskedDB = em[hLen+1:]
208 # Step 3c
209 seedMask = self._mgf(maskedDB, hLen)
210 # Step 3d
211 seed = strxor(maskedSeed, seedMask)
212 # Step 3e
213 dbMask = self._mgf(seed, k-hLen-1)
214 # Step 3f
215 db = strxor(maskedDB, dbMask)
216 # Step 3g
217 valid = 1
218 one = db[hLen:].find(bchr(0x01))
219 lHash1 = db[:hLen]
220 if lHash1!=lHash:
221 valid = 0
222 if one<0:
223 valid = 0
224 if bord(y)!=0:
225 valid = 0
226 if not valid:
227 raise ValueError("Incorrect decryption.")
228 # Step 4
229 return db[hLen+one+1:]
230
231 def new(key, hashAlgo=None, mgfunc=None, label=b('')):
232 """Return a cipher object `PKCS1OAEP_Cipher` that can be used to perform PKC S#1 OAEP encryption or decryption.
233
234 :Parameters:
235 key : RSA key object
236 The key to use to encrypt or decrypt the message. This is a `Crypto.Public Key.RSA` object.
237 Decryption is only possible if *key* is a private RSA key.
238 hashAlgo : hash object
239 The hash function to use. This can be a module under `Crypto.Hash`
240 or an existing hash object created from any of such modules. If not specif ied,
241 `Crypto.Hash.SHA` (that is, SHA-1) is used.
242 mgfunc : callable
243 A mask generation function that accepts two parameters: a string to
244 use as seed, and the lenth of the mask to generate, in bytes.
245 If not specified, the standard MGF1 is used (a safe choice).
246 label : string
247 A label to apply to this particular encryption. If not specified,
248 an empty string is used. Specifying a label does not improve
249 security.
250
251 :attention: Modify the mask generation function only if you know what you ar e doing.
252 Sender and receiver must use the same one.
253 """
254 return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label)
255
OLDNEW
« no previous file with comments | « third_party/google-endpoints/Crypto/Cipher/DES3.py ('k') | third_party/google-endpoints/Crypto/Cipher/PKCS1_v1_5.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698