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

Side by Side Diff: third_party/google-endpoints/Crypto/PublicKey/RSA.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 # PublicKey/RSA.py : RSA public key primitive
4 #
5 # Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
6 #
7 # ===================================================================
8 # The contents of this file are dedicated to the public domain. To
9 # the extent that dedication to the public domain is not available,
10 # everyone is granted a worldwide, perpetual, royalty-free,
11 # non-exclusive license to exercise all rights associated with the
12 # contents of this file for any purpose whatsoever.
13 # No rights are reserved.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 # SOFTWARE.
23 # ===================================================================
24
25 """RSA public-key cryptography algorithm (signature and encryption).
26
27 RSA_ is the most widespread and used public key algorithm. Its security is
28 based on the difficulty of factoring large integers. The algorithm has
29 withstood attacks for 30 years, and it is therefore considered reasonably
30 secure for new designs.
31
32 The algorithm can be used for both confidentiality (encryption) and
33 authentication (digital signature). It is worth noting that signing and
34 decryption are significantly slower than verification and encryption.
35 The cryptograhic strength is primarily linked to the length of the modulus *n*.
36 In 2012, a sufficient length is deemed to be 2048 bits. For more information,
37 see the most recent ECRYPT_ report.
38
39 Both RSA ciphertext and RSA signature are as big as the modulus *n* (256
40 bytes if *n* is 2048 bit long).
41
42 This module provides facilities for generating fresh, new RSA keys, constructing
43 them from known components, exporting them, and importing them.
44
45 >>> from Crypto.PublicKey import RSA
46 >>>
47 >>> key = RSA.generate(2048)
48 >>> f = open('mykey.pem','w')
49 >>> f.write(RSA.exportKey('PEM'))
50 >>> f.close()
51 ...
52 >>> f = open('mykey.pem','r')
53 >>> key = RSA.importKey(f.read())
54
55 Even though you may choose to directly use the methods of an RSA key object
56 to perform the primitive cryptographic operations (e.g. `_RSAobj.encrypt`),
57 it is recommended to use one of the standardized schemes instead (like
58 `Crypto.Cipher.PKCS1_v1_5` or `Crypto.Signature.PKCS1_v1_5`).
59
60 .. _RSA: http://en.wikipedia.org/wiki/RSA_%28algorithm%29
61 .. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
62
63 :sort: generate,construct,importKey,error
64 """
65
66 __revision__ = "$Id$"
67
68 __all__ = ['generate', 'construct', 'error', 'importKey', 'RSAImplementation', ' _RSAobj']
69
70 import sys
71 if sys.version_info[0] == 2 and sys.version_info[1] == 1:
72 from Crypto.Util.py21compat import *
73 from Crypto.Util.py3compat import *
74 #from Crypto.Util.python_compat import *
75 from Crypto.Util.number import getRandomRange, bytes_to_long, long_to_bytes
76
77 from Crypto.PublicKey import _RSA, _slowmath, pubkey
78 from Crypto import Random
79
80 from Crypto.Util.asn1 import DerObject, DerSequence, DerNull
81 import binascii
82 import struct
83
84 from Crypto.Util.number import inverse
85
86 from Crypto.Util.number import inverse
87
88 try:
89 from Crypto.PublicKey import _fastmath
90 except ImportError:
91 _fastmath = None
92
93 class _RSAobj(pubkey.pubkey):
94 """Class defining an actual RSA key.
95
96 :undocumented: __getstate__, __setstate__, __repr__, __getattr__
97 """
98 #: Dictionary of RSA parameters.
99 #:
100 #: A public key will only have the following entries:
101 #:
102 #: - **n**, the modulus.
103 #: - **e**, the public exponent.
104 #:
105 #: A private key will also have:
106 #:
107 #: - **d**, the private exponent.
108 #: - **p**, the first factor of n.
109 #: - **q**, the second factor of n.
110 #: - **u**, the CRT coefficient (1/p) mod q.
111 keydata = ['n', 'e', 'd', 'p', 'q', 'u']
112
113 def __init__(self, implementation, key, randfunc=None):
114 self.implementation = implementation
115 self.key = key
116 if randfunc is None:
117 randfunc = Random.new().read
118 self._randfunc = randfunc
119
120 def __getattr__(self, attrname):
121 if attrname in self.keydata:
122 # For backward compatibility, allow the user to get (not set) the
123 # RSA key parameters directly from this object.
124 return getattr(self.key, attrname)
125 else:
126 raise AttributeError("%s object has no %r attribute" % (self.__class __.__name__, attrname,))
127
128 def encrypt(self, plaintext, K):
129 """Encrypt a piece of data with RSA.
130
131 :Parameter plaintext: The piece of data to encrypt with RSA. It may not
132 be numerically larger than the RSA module (**n**).
133 :Type plaintext: byte string or long
134
135 :Parameter K: A random parameter (*for compatibility only. This
136 value will be ignored*)
137 :Type K: byte string or long
138
139 :attention: this function performs the plain, primitive RSA encryption
140 (*textbook*). In real applications, you always need to use proper
141 cryptographic padding, and you should not directly encrypt data with
142 this method. Failure to do so may lead to security vulnerabilities.
143 It is recommended to use modules
144 `Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead.
145
146 :Return: A tuple with two items. The first item is the ciphertext
147 of the same type as the plaintext (string or long). The second item
148 is always None.
149 """
150 return pubkey.pubkey.encrypt(self, plaintext, K)
151
152 def decrypt(self, ciphertext):
153 """Decrypt a piece of data with RSA.
154
155 Decryption always takes place with blinding.
156
157 :attention: this function performs the plain, primitive RSA decryption
158 (*textbook*). In real applications, you always need to use proper
159 cryptographic padding, and you should not directly decrypt data with
160 this method. Failure to do so may lead to security vulnerabilities.
161 It is recommended to use modules
162 `Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead.
163
164 :Parameter ciphertext: The piece of data to decrypt with RSA. It may
165 not be numerically larger than the RSA module (**n**). If a tuple,
166 the first item is the actual ciphertext; the second item is ignored.
167
168 :Type ciphertext: byte string, long or a 2-item tuple as returned by
169 `encrypt`
170
171 :Return: A byte string if ciphertext was a byte string or a tuple
172 of byte strings. A long otherwise.
173 """
174 return pubkey.pubkey.decrypt(self, ciphertext)
175
176 def sign(self, M, K):
177 """Sign a piece of data with RSA.
178
179 Signing always takes place with blinding.
180
181 :attention: this function performs the plain, primitive RSA decryption
182 (*textbook*). In real applications, you always need to use proper
183 cryptographic padding, and you should not directly sign data with
184 this method. Failure to do so may lead to security vulnerabilities.
185 It is recommended to use modules
186 `Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead.
187
188 :Parameter M: The piece of data to sign with RSA. It may
189 not be numerically larger than the RSA module (**n**).
190 :Type M: byte string or long
191
192 :Parameter K: A random parameter (*for compatibility only. This
193 value will be ignored*)
194 :Type K: byte string or long
195
196 :Return: A 2-item tuple. The first item is the actual signature (a
197 long). The second item is always None.
198 """
199 return pubkey.pubkey.sign(self, M, K)
200
201 def verify(self, M, signature):
202 """Verify the validity of an RSA signature.
203
204 :attention: this function performs the plain, primitive RSA encryption
205 (*textbook*). In real applications, you always need to use proper
206 cryptographic padding, and you should not directly verify data with
207 this method. Failure to do so may lead to security vulnerabilities.
208 It is recommended to use modules
209 `Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead.
210
211 :Parameter M: The expected message.
212 :Type M: byte string or long
213
214 :Parameter signature: The RSA signature to verify. The first item of
215 the tuple is the actual signature (a long not larger than the modulus
216 **n**), whereas the second item is always ignored.
217 :Type signature: A 2-item tuple as return by `sign`
218
219 :Return: True if the signature is correct, False otherwise.
220 """
221 return pubkey.pubkey.verify(self, M, signature)
222
223 def _encrypt(self, c, K):
224 return (self.key._encrypt(c),)
225
226 def _decrypt(self, c):
227 #(ciphertext,) = c
228 (ciphertext,) = c[:1] # HACK - We should use the previous line
229 # instead, but this is more compatible and we're
230 # going to replace the Crypto.PublicKey API soon
231 # anyway.
232
233 # Blinded RSA decryption (to prevent timing attacks):
234 # Step 1: Generate random secret blinding factor r, such that 0 < r < n- 1
235 r = getRandomRange(1, self.key.n-1, randfunc=self._randfunc)
236 # Step 2: Compute c' = c * r**e mod n
237 cp = self.key._blind(ciphertext, r)
238 # Step 3: Compute m' = c'**d mod n (ordinary RSA decryption)
239 mp = self.key._decrypt(cp)
240 # Step 4: Compute m = m**(r-1) mod n
241 return self.key._unblind(mp, r)
242
243 def _blind(self, m, r):
244 return self.key._blind(m, r)
245
246 def _unblind(self, m, r):
247 return self.key._unblind(m, r)
248
249 def _sign(self, m, K=None):
250 return (self.key._sign(m),)
251
252 def _verify(self, m, sig):
253 #(s,) = sig
254 (s,) = sig[:1] # HACK - We should use the previous line instead, but
255 # this is more compatible and we're going to replace
256 # the Crypto.PublicKey API soon anyway.
257 return self.key._verify(m, s)
258
259 def has_private(self):
260 return self.key.has_private()
261
262 def size(self):
263 return self.key.size()
264
265 def can_blind(self):
266 return True
267
268 def can_encrypt(self):
269 return True
270
271 def can_sign(self):
272 return True
273
274 def publickey(self):
275 return self.implementation.construct((self.key.n, self.key.e))
276
277 def __getstate__(self):
278 d = {}
279 for k in self.keydata:
280 try:
281 d[k] = getattr(self.key, k)
282 except AttributeError:
283 pass
284 return d
285
286 def __setstate__(self, d):
287 if not hasattr(self, 'implementation'):
288 self.implementation = RSAImplementation()
289 t = []
290 for k in self.keydata:
291 if not d.has_key(k):
292 break
293 t.append(d[k])
294 self.key = self.implementation._math.rsa_construct(*tuple(t))
295
296 def __repr__(self):
297 attrs = []
298 for k in self.keydata:
299 if k == 'n':
300 attrs.append("n(%d)" % (self.size()+1,))
301 elif hasattr(self.key, k):
302 attrs.append(k)
303 if self.has_private():
304 attrs.append("private")
305 # PY3K: This is meant to be text, do not change to bytes (data)
306 return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(at trs))
307
308 def exportKey(self, format='PEM', passphrase=None, pkcs=1):
309 """Export this RSA key.
310
311 :Parameter format: The format to use for wrapping the key.
312
313 - *'DER'*. Binary encoding, always unencrypted.
314 - *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_ .
315 Unencrypted (default) or encrypted.
316 - *'OpenSSH'*. Textual encoding, done according to OpenSSH specifica tion.
317 Only suitable for public keys (not private keys).
318 :Type format: string
319
320 :Parameter passphrase: In case of PEM, the pass phrase to derive the enc ryption key from.
321 :Type passphrase: string
322
323 :Parameter pkcs: The PKCS standard to follow for assembling the key.
324 You have two choices:
325
326 - with **1**, the public key is embedded into an X.509 `SubjectPublicK eyInfo` DER SEQUENCE.
327 The private key is embedded into a `PKCS#1`_ `RSAPrivateKey` DER SEQ UENCE.
328 This mode is the default.
329 - with **8**, the private key is embedded into a `PKCS#8`_ `PrivateKey Info` DER SEQUENCE.
330 This mode is not available for public keys.
331
332 PKCS standards are not relevant for the *OpenSSH* format.
333 :Type pkcs: integer
334
335 :Return: A byte string with the encoded public or private half.
336 :Raise ValueError:
337 When the format is unknown.
338
339 .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
340 .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
341 .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
342 .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
343 """
344 if passphrase is not None:
345 passphrase = tobytes(passphrase)
346 if format=='OpenSSH':
347 eb = long_to_bytes(self.e)
348 nb = long_to_bytes(self.n)
349 if bord(eb[0]) & 0x80: eb=bchr(0x00)+eb
350 if bord(nb[0]) & 0x80: nb=bchr(0x00)+nb
351 keyparts = [ 'ssh-rsa', eb, nb ]
352 keystring = ''.join([ struct.pack(">I",len(kp))+kp for kp in keyp arts])
353 return 'ssh-rsa '+binascii.b2a_base64(keystring)[:-1]
354
355 # DER format is always used, even in case of PEM, which simply
356 # encodes it into BASE64.
357 der = DerSequence()
358 if self.has_private():
359 keyType= { 1: 'RSA PRIVATE', 8: 'PRIVATE' }[pkcs]
360 der[:] = [ 0, self.n, self.e, self.d, self.p, self.q,
361 self.d % (self.p-1), self.d % (self.q-1),
362 inverse(self.q, self.p) ]
363 if pkcs==8:
364 derkey = der.encode()
365 der = DerSequence([0])
366 der.append(algorithmIdentifier)
367 der.append(DerObject('OCTET STRING', derkey).encode())
368 else:
369 keyType = "PUBLIC"
370 der.append(algorithmIdentifier)
371 bitmap = DerObject('BIT STRING')
372 derPK = DerSequence( [ self.n, self.e ] )
373 bitmap.payload = bchr(0x00) + derPK.encode()
374 der.append(bitmap.encode())
375 if format=='DER':
376 return der.encode()
377 if format=='PEM':
378 pem = b("-----BEGIN " + keyType + " KEY-----\n")
379 objenc = None
380 if passphrase and keyType.endswith('PRIVATE'):
381 # We only support 3DES for encryption
382 import Crypto.Hash.MD5
383 from Crypto.Cipher import DES3
384 from Crypto.Protocol.KDF import PBKDF1
385 salt = self._randfunc(8)
386 key = PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
387 key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD5)
388 objenc = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt)
389 pem += b('Proc-Type: 4,ENCRYPTED\n')
390 pem += b('DEK-Info: DES-EDE3-CBC,') + binascii.b2a_hex(salt) .upper() + b('\n\n')
391
392 binaryKey = der.encode()
393 if objenc:
394 # Add PKCS#7-like padding
395 padding = objenc.block_size-len(binaryKey)%objenc.block_size
396 binaryKey = objenc.encrypt(binaryKey+bchr(padding)*padding)
397
398 # Each BASE64 line can take up to 64 characters (=48 bytes of da ta)
399 chunks = [ binascii.b2a_base64(binaryKey[i:i+48]) for i in range (0, len(binaryKey), 48) ]
400 pem += b('').join(chunks)
401 pem += b("-----END " + keyType + " KEY-----")
402 return pem
403 return ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
404
405 class RSAImplementation(object):
406 """
407 An RSA key factory.
408
409 This class is only internally used to implement the methods of the `Crypto.P ublicKey.RSA` module.
410
411 :sort: __init__,generate,construct,importKey
412 :undocumented: _g*, _i*
413 """
414
415 def __init__(self, **kwargs):
416 """Create a new RSA key factory.
417
418 :Keywords:
419 use_fast_math : bool
420 Specify which mathematic library to use:
421
422 - *None* (default). Use fastest math available.
423 - *True* . Use fast math.
424 - *False* . Use slow math.
425 default_randfunc : callable
426 Specify how to collect random data:
427
428 - *None* (default). Use Random.new().read().
429 - not *None* . Use the specified function direct ly.
430 :Raise RuntimeError:
431 When **use_fast_math** =True but fast math is not available.
432 """
433 use_fast_math = kwargs.get('use_fast_math', None)
434 if use_fast_math is None: # Automatic
435 if _fastmath is not None:
436 self._math = _fastmath
437 else:
438 self._math = _slowmath
439
440 elif use_fast_math: # Explicitly select fast math
441 if _fastmath is not None:
442 self._math = _fastmath
443 else:
444 raise RuntimeError("fast math module not available")
445
446 else: # Explicitly select slow math
447 self._math = _slowmath
448
449 self.error = self._math.error
450
451 self._default_randfunc = kwargs.get('default_randfunc', None)
452 self._current_randfunc = None
453
454 def _get_randfunc(self, randfunc):
455 if randfunc is not None:
456 return randfunc
457 elif self._current_randfunc is None:
458 self._current_randfunc = Random.new().read
459 return self._current_randfunc
460
461 def generate(self, bits, randfunc=None, progress_func=None, e=65537):
462 """Randomly generate a fresh, new RSA key.
463
464 :Parameters:
465 bits : int
466 Key length, or size (in bits) of the RSA modulus.
467 It must be a multiple of 256, and no smaller than 10 24.
468
469 randfunc : callable
470 Random number generation function; it should accept
471 a single integer N and return a string of random dat a
472 N bytes long.
473 If not specified, a new one will be instantiated
474 from ``Crypto.Random``.
475
476 progress_func : callable
477 Optional function that will be called with a short s tring
478 containing the key parameter currently being generat ed;
479 it's useful for interactive applications where a use r is
480 waiting for a key to be generated.
481
482 e : int
483 Public RSA exponent. It must be an odd positive inte ger.
484 It is typically a small number with very few ones in its
485 binary representation.
486 The default value 65537 (= ``0b10000000000000001`` ) is a safe
487 choice: other common values are 5, 7, 17, and 257.
488
489 :attention: You should always use a cryptographically secure random numb er generator,
490 such as the one defined in the ``Crypto.Random`` module; **don't** j ust use the
491 current time and the ``random`` module.
492
493 :attention: Exponent 3 is also widely used, but it requires very special care when padding
494 the message.
495
496 :Return: An RSA key object (`_RSAobj`).
497
498 :Raise ValueError:
499 When **bits** is too little or not a multiple of 256, or when
500 **e** is not odd or smaller than 2.
501 """
502 if bits < 1024 or (bits & 0xff) != 0:
503 # pubkey.getStrongPrime doesn't like anything that's not a multiple of 256 and >= 1024
504 raise ValueError("RSA modulus length must be a multiple of 256 and > = 1024")
505 if e%2==0 or e<3:
506 raise ValueError("RSA public exponent must be a positive, odd intege r larger than 2.")
507 rf = self._get_randfunc(randfunc)
508 obj = _RSA.generate_py(bits, rf, progress_func, e) # TODO: Don't use legacy _RSA module
509 key = self._math.rsa_construct(obj.n, obj.e, obj.d, obj.p, obj.q, obj.u)
510 return _RSAobj(self, key)
511
512 def construct(self, tup):
513 """Construct an RSA key from a tuple of valid RSA components.
514
515 The modulus **n** must be the product of two primes.
516 The public exponent **e** must be odd and larger than 1.
517
518 In case of a private key, the following equations must apply:
519
520 - e != 1
521 - p*q = n
522 - e*d = 1 mod (p-1)(q-1)
523 - p*u = 1 mod q
524
525 :Parameters:
526 tup : tuple
527 A tuple of long integers, with at least 2 and no
528 more than 6 items. The items come in the following order:
529
530 1. RSA modulus (n).
531 2. Public exponent (e).
532 3. Private exponent (d). Only required if the key is private .
533 4. First factor of n (p). Optional.
534 5. Second factor of n (q). Optional.
535 6. CRT coefficient, (1/p) mod q (u). Optional.
536
537 :Return: An RSA key object (`_RSAobj`).
538 """
539 key = self._math.rsa_construct(*tup)
540 return _RSAobj(self, key)
541
542 def _importKeyDER(self, externKey):
543 """Import an RSA key (public or private half), encoded in DER form."""
544
545 try:
546
547 der = DerSequence()
548 der.decode(externKey, True)
549
550 # Try PKCS#1 first, for a private key
551 if len(der)==9 and der.hasOnlyInts() and der[0]==0:
552 # ASN.1 RSAPrivateKey element
553 del der[6:] # Remove d mod (p-1), d mod (q-1), and q^{-1} mo d p
554 der.append(inverse(der[4],der[5])) # Add p^{-1} mod q
555 del der[0] # Remove version
556 return self.construct(der[:])
557
558 # Keep on trying PKCS#1, but now for a public key
559 if len(der)==2:
560 # The DER object is an RSAPublicKey SEQUENCE with two elements
561 if der.hasOnlyInts():
562 return self.construct(der[:])
563 # The DER object is a SubjectPublicKeyInfo SEQUENCE with two ele ments:
564 # an 'algorithm' (or 'algorithmIdentifier') SEQUENCE and a 'subj ectPublicKey' BIT STRING.
565 # 'algorithm' takes the value given a few lines above.
566 # 'subjectPublicKey' encapsulates the actual ASN.1 RSAPublicKey element.
567 if der[0]==algorithmIdentifier:
568 bitmap = DerObject()
569 bitmap.decode(der[1], True)
570 if bitmap.isType('BIT STRING') and bord(bitmap.payload[0 ])==0x00:
571 der.decode(bitmap.payload[1:], True)
572 if len(der)==2 and der.hasOnlyInts():
573 return self.construct(der[:])
574
575 # Try unencrypted PKCS#8
576 if der[0]==0:
577 # The second element in the SEQUENCE is algorithmIdentifier.
578 # It must say RSA (see above for description).
579 if der[1]==algorithmIdentifier:
580 privateKey = DerObject()
581 privateKey.decode(der[2], True)
582 if privateKey.isType('OCTET STRING'):
583 return self._importKeyDER(privateKey.payload)
584
585 except ValueError, IndexError:
586 pass
587
588 raise ValueError("RSA key format is not supported")
589
590 def importKey(self, externKey, passphrase=None):
591 """Import an RSA key (public or private half), encoded in standard form.
592
593 :Parameter externKey:
594 The RSA key to import, encoded as a string.
595
596 An RSA public key can be in any of the following formats:
597
598 - X.509 `subjectPublicKeyInfo` DER SEQUENCE (binary or PEM encoding)
599 - `PKCS#1`_ `RSAPublicKey` DER SEQUENCE (binary or PEM encoding)
600 - OpenSSH (textual public key only)
601
602 An RSA private key can be in any of the following formats:
603
604 - PKCS#1 `RSAPrivateKey` DER SEQUENCE (binary or PEM encoding)
605 - `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE (binary or PEM encoding)
606 - OpenSSH (textual public key only)
607
608 For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
609
610 In case of PEM encoding, the private key can be encrypted with DES o r 3TDES according to a certain ``pass phrase``.
611 Only OpenSSL-compatible pass phrases are supported.
612 :Type externKey: string
613
614 :Parameter passphrase:
615 In case of an encrypted PEM key, this is the pass phrase from which the encryption key is derived.
616 :Type passphrase: string
617
618 :Return: An RSA key object (`_RSAobj`).
619
620 :Raise ValueError/IndexError/TypeError:
621 When the given key cannot be parsed (possibly because the pass phras e is wrong).
622
623 .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
624 .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
625 .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
626 .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
627 """
628 externKey = tobytes(externKey)
629 if passphrase is not None:
630 passphrase = tobytes(passphrase)
631
632 if externKey.startswith(b('-----')):
633 # This is probably a PEM encoded key
634 lines = externKey.replace(b(" "),b('')).split()
635 keyobj = None
636
637 # The encrypted PEM format
638 if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
639 DEK = lines[2].split(b(':'))
640 if len(DEK)!=2 or DEK[0]!=b('DEK-Info') or not passphrase:
641 raise ValueError("PEM encryption format not supported.")
642 algo, salt = DEK[1].split(b(','))
643 salt = binascii.a2b_hex(salt)
644 import Crypto.Hash.MD5
645 from Crypto.Cipher import DES, DES3
646 from Crypto.Protocol.KDF import PBKDF1
647 if algo==b("DES-CBC"):
648 # This is EVP_BytesToKey in OpenSSL
649 key = PBKDF1(passphrase, salt, 8, 1, Crypto.Hash.MD5)
650 keyobj = DES.new(key, Crypto.Cipher.DES.MODE_CBC, salt)
651 elif algo==b("DES-EDE3-CBC"):
652 # Note that EVP_BytesToKey is note exactly the same as P BKDF1
653 key = PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
654 key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD 5)
655 keyobj = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt )
656 else:
657 raise ValueError("Unsupport PEM encryption algorithm.")
658 lines = lines[2:]
659
660 der = binascii.a2b_base64(b('').join(lines[1:-1]))
661 if keyobj:
662 der = keyobj.decrypt(der)
663 padding = bord(der[-1])
664 der = der[:-padding]
665 return self._importKeyDER(der)
666
667 if externKey.startswith(b('ssh-rsa ')):
668 # This is probably an OpenSSH key
669 keystring = binascii.a2b_base64(externKey.split(b(' '))[1])
670 keyparts = []
671 while len(keystring)>4:
672 l = struct.unpack(">I",keystring[:4])[0]
673 keyparts.append(keystring[4:4+l])
674 keystring = keystring[4+l:]
675 e = bytes_to_long(keyparts[1])
676 n = bytes_to_long(keyparts[2])
677 return self.construct([n, e])
678 if bord(externKey[0])==0x30:
679 # This is probably a DER encoded key
680 return self._importKeyDER(externKey)
681
682 raise ValueError("RSA key format is not supported")
683
684 #: This is the ASN.1 DER object that qualifies an algorithm as
685 #: compliant to PKCS#1 (that is, the standard RSA).
686 # It is found in all 'algorithm' fields (also called 'algorithmIdentifier').
687 # It is a SEQUENCE with the oid assigned to RSA and with its parameters (none).
688 # 0x06 0x09 OBJECT IDENTIFIER, 9 bytes of payload
689 # 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01
690 # rsaEncryption (1 2 840 113549 1 1 1) (PKCS #1)
691 # 0x05 0x00 NULL
692 algorithmIdentifier = DerSequence(
693 [ b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'),
694 DerNull().encode() ]
695 ).encode()
696
697 _impl = RSAImplementation()
698 #:
699 #: Randomly generate a fresh, new RSA key object.
700 #:
701 #: See `RSAImplementation.generate`.
702 #:
703 generate = _impl.generate
704 #:
705 #: Construct an RSA key object from a tuple of valid RSA components.
706 #:
707 #: See `RSAImplementation.construct`.
708 #:
709 construct = _impl.construct
710 #:
711 #: Import an RSA key (public or private half), encoded in standard form.
712 #:
713 #: See `RSAImplementation.importKey`.
714 #:
715 importKey = _impl.importKey
716 error = _impl.error
717
718 # vim:set ts=4 sw=4 sts=4 expandtab:
719
OLDNEW
« no previous file with comments | « third_party/google-endpoints/Crypto/PublicKey/ElGamal.py ('k') | third_party/google-endpoints/Crypto/PublicKey/_DSA.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698