diff options
author | Legrandin <gooksankoo@hoiptorrow.mailexpire.com> | 2012-04-10 21:26:33 +0200 |
---|---|---|
committer | Legrandin <gooksankoo@hoiptorrow.mailexpire.com> | 2012-04-10 21:26:33 +0200 |
commit | a7123247de876c8bafbd1d60a349d861e7111d58 (patch) | |
tree | 386c567ae57bb64998cd04c7482bffb2571920e2 | |
parent | 7ad012fae30f558e40efdd541e4e6503e47343b1 (diff) | |
download | pycrypto-a7123247de876c8bafbd1d60a349d861e7111d58.tar.gz |
Refreshed documentation for RSA. epydoc does not generate documentation for private methods, and inherited ones are made more explicit.
-rw-r--r-- | Doc/epydoc-config | 7 | ||||
-rw-r--r-- | lib/Crypto/PublicKey/DSA.py | 2 | ||||
-rw-r--r-- | lib/Crypto/PublicKey/RSA.py | 147 | ||||
-rw-r--r-- | lib/Crypto/PublicKey/pubkey.py | 122 |
4 files changed, 234 insertions, 44 deletions
diff --git a/Doc/epydoc-config b/Doc/epydoc-config index 018e461..c71d200 100644 --- a/Doc/epydoc-config +++ b/Doc/epydoc-config @@ -8,6 +8,13 @@ output: html target: Doc/apidoc/ sourcecode: no +# Do not include private variables +private: no + +# Include the complete set of inherited methods, but grouped in a special +# section +inheritance: grouped + name: PyCrypto API Documentation url: http://www.pycrypto.org/ diff --git a/lib/Crypto/PublicKey/DSA.py b/lib/Crypto/PublicKey/DSA.py index 5c349a9..71254a5 100644 --- a/lib/Crypto/PublicKey/DSA.py +++ b/lib/Crypto/PublicKey/DSA.py @@ -26,7 +26,7 @@ __revision__ = "$Id$" -__all__ = ['generate', 'construct', 'error'] +__all__ = ['generate', 'construct', 'error', 'DSAImplementation', '_DSAobj'] import sys if sys.version_info[0] == 2 and sys.version_info[1] == 1: diff --git a/lib/Crypto/PublicKey/RSA.py b/lib/Crypto/PublicKey/RSA.py index 1e3a433..8849985 100644 --- a/lib/Crypto/PublicKey/RSA.py +++ b/lib/Crypto/PublicKey/RSA.py @@ -24,13 +24,45 @@ """RSA public-key cryptography algorithm. +RSA_ is the most widespread and used public key algorithm. Its security is +based on the difficulty of factoring large integers. The algorithm has +withstood attacks for 30 years, and it is therefore considered reasonably +secure for new designs. + +The algorithm can be used for both confidentiality (encryption) and +authentication (digital signature). It is worth noting that signing and +decryption are significantly slower than verification and encryption. +The cryptograhic strength is primarily linked to the length of the modulus. +In 2012, a sufficient length is deemed to be 2048 bits. For more information, +see the most recent ECRYPT_ report. + +This module provides facilities for generating fresh, new RSA keys, constructing +them from known components, exporting them, and importing them. + + >>> from Crypto.PublicKey import RSA + >>> + >>> key = RSA.generate(2048) + >>> f = open('mykey.pem','w') + >>> f.write(RSA.exportKey('PEM')) + >>> f.close() + ... + >>> f = open('mykey.pem','r') + >>> key = RSA.importKey(f.read()) + +Even though you may choose to directly use the methods of an RSA key object +to perform the primitive cryptographic operations (e.g. `_RSAobj.encrypt`), +it is recommended to use one of the standardized schemes instead (like +`Crypto.Cipher.PKCS1_v1_5` or `Crypto.Signature.PKCS1_v1_5`). + +.. _RSA: http://en.wikipedia.org/wiki/RSA_%28algorithm%29 +.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf + :sort: generate,construct,importKey,error -:undocumented: _fastmath, __revision__, _impl """ __revision__ = "$Id$" -__all__ = ['generate', 'construct', 'error', 'importKey' ] +__all__ = ['generate', 'construct', 'error', 'importKey', 'RSAImplementation', '_RSAobj'] import sys if sys.version_info[0] == 2 and sys.version_info[1] == 1: @@ -56,8 +88,10 @@ except ImportError: _fastmath = None class _RSAobj(pubkey.pubkey): - """Class defining an actual RSA key.""" + """Class defining an actual RSA key. + :undocumented: __getstate__, __setstate__, __repr__, __getattr__ + """ #: Dictionary of RSA parameters. #: #: A public key will only have the following entries: @@ -88,6 +122,101 @@ class _RSAobj(pubkey.pubkey): else: raise AttributeError("%s object has no %r attribute" % (self.__class__.__name__, attrname,)) + def encrypt(self, plaintext, K): + """Encrypt a piece of data with RSA. + + :Parameter plaintext: The piece of data to encrypt with RSA. It may not + be numerically larger than the RSA module (**n**). + :Type plaintext: byte string or long + + :Parameter K: A random parameter (*for compatibility only. This + value will be ignored*) + :Type K: byte string or long + + :attention: this function performs the plain, primitive RSA encryption + (*schoolbook*). In real applications, you always need to use proper + cryptographic padding, and you should not directly encrypt data with + this method. Failure to do so may lead to security vulnerabilities. + It is recommended to use modules + `Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead. + + :Return: A tuple with two items. The first item is the ciphertext + of the same type as the plaintext (string or long). The second item + is always None. + """ + return pubkey.pubkey.encrypt(self, plaintext, K) + + def decrypt(self, ciphertext): + """Decrypt a piece of data with RSA. + + Decryption always takes place with blinding. + + :attention: this function performs the plain, primitive RSA decryption + (*schoolbook*). In real applications, you always need to use proper + cryptographic padding, and you should not directly decrypt data with + this method. Failure to do so may lead to security vulnerabilities. + It is recommended to use modules + `Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead. + + :Parameter ciphertext: The piece of data to decrypt with RSA. It may + not be numerically larger than the RSA module (**n**). If a tuple, + the first item is the actual ciphertext; the second item is ignored. + + :Type ciphertext: byte string, long or a 2-item tuple as returned by + `encrypt` + + :Return: A byte string if ciphertext was a byte string or a tuple + of byte strings. A long otherwise. + """ + return pubkey.pubkey.decrypt(self, ciphertext) + + def sign(self, M, K): + """Sign a piece of data with RSA. + + Signing always takes place with blinding. + + :attention: this function performs the plain, primitive RSA decryption + (*schoolbook*). In real applications, you always need to use proper + cryptographic padding, and you should not directly sign data with + this method. Failure to do so may lead to security vulnerabilities. + It is recommended to use modules + `Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead. + + :Parameter M: The piece of data to sign with RSA. It may + not be numerically larger than the RSA module (**n**). + :Type M: byte string or long + + :Parameter K: A random parameter (*for compatibility only. This + value will be ignored*) + :Type K: byte string or long + + :Return: A 2-item tuple. The first item is the actual signature (a + long). The second item is always None. + """ + return pubkey.pubkey.sign(self, M, K) + + def verify(self, M, signature): + """Verify the validity of an RSA signature. + + :attention: this function performs the plain, primitive RSA encryption + (*schoolbook*). In real applications, you always need to use proper + cryptographic padding, and you should not directly verify data with + this method. Failure to do so may lead to security vulnerabilities. + It is recommended to use modules + `Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead. + + :Parameter M: The expected message. + :Type M: byte string or long + + :Parameter signature: The RSA signature to verify. The first item of + the tuple is the actual signature (a long not larger than the modulus + **n**), whereas the second item is always ignored. + :Type signature: A 2-item tuple as return by `sign` + + :Return: True if the signature is correct, False otherwise. + """ + return pubkey.pubkey.verify(self, M, signature) + def _encrypt(self, c, K): return (self.key._encrypt(c),) @@ -195,7 +324,7 @@ class _RSAobj(pubkey.pubkey): PKCS standards are not relevant for the *OpenSSH* format. :Type pkcs: integer - :Return: A string with the encoded public or private half. + :Return: A byte string with the encoded public or private half. :Raise ValueError: When the format is unknown. """ @@ -317,7 +446,7 @@ class RSAImplementation(object): return self._current_randfunc def generate(self, bits, randfunc=None, progress_func=None, e=65537): - """Randomly generate a fresh, new RSA key object. + """Randomly generate a fresh, new RSA key. :Parameters: bits : int @@ -349,6 +478,8 @@ class RSAImplementation(object): :attention: Exponent 3 is also widely used, but it requires very special care when padding the message. + :Return: An RSA key object (`_RSAobj`). + :Raise ValueError: When **bits** is too little or not a multiple of 256, or when **e** is not odd or smaller than 2. @@ -364,7 +495,7 @@ class RSAImplementation(object): return _RSAobj(self, key) def construct(self, tup): - """Construct an RSA key object from a tuple of valid RSA components. + """Construct an RSA key from a tuple of valid RSA components. The modulus **n** must be the product of two primes. The public exponent **e** must be odd and larger than 1. @@ -387,6 +518,8 @@ class RSAImplementation(object): 4. First factor of n (p). Optional. 5. Second factor of n (q). Optional. 6. CRT coefficient, (1/p) mod q (u). Optional. + + :Return: An RSA key object (`_RSAobj`). """ key = self._math.rsa_construct(*tup) return _RSAobj(self, key) @@ -458,6 +591,8 @@ class RSAImplementation(object): In case of an encrypted PEM key, this is the pass phrase from which the encryption key is derived. :Type passphrase: string + :Return: An RSA key object (`_RSAobj`). + :Raise ValueError/IndexError/TypeError: When the given key cannot be parsed (possibly because the pass phrase is wrong). """ diff --git a/lib/Crypto/PublicKey/pubkey.py b/lib/Crypto/PublicKey/pubkey.py index 90f4603..e44de8f 100644 --- a/lib/Crypto/PublicKey/pubkey.py +++ b/lib/Crypto/PublicKey/pubkey.py @@ -31,6 +31,10 @@ from Crypto.Util.number import * # Basic public key class class pubkey: + """An abstract class for a public key object. + + :undocumented: __getstate__, __setstate__, __eq__, __ne__, validate + """ def __init__(self): pass @@ -52,9 +56,16 @@ integers, MPZ objects, or whatever.""" if d.has_key(key): self.__dict__[key]=bignum(d[key]) def encrypt(self, plaintext, K): - """encrypt(plaintext:string|long, K:string|long) : tuple - Encrypt the string or integer plaintext. K is a random - parameter required by some algorithms. + """Encrypt a piece of data. + + :Parameter plaintext: The piece of data to encrypt. + :Type plaintext: byte string or long + + :Parameter K: A random parameter required by some algorithms + :Type K: byte string or long + + :Return: A tuple with two items. Each item is of the same type as the + plaintext (string or long). """ wasString=0 if isinstance(plaintext, types.StringType): @@ -66,8 +77,13 @@ integers, MPZ objects, or whatever.""" else: return ciphertext def decrypt(self, ciphertext): - """decrypt(ciphertext:tuple|string|long): string - Decrypt 'ciphertext' using this key. + """Decrypt a piece of data. + + :Parameter ciphertext: The piece of data to decrypt. + :Type ciphertext: byte string, long or a 2-item tuple as returned by `encrypt` + + :Return: A byte string if ciphertext was a byte string or a tuple + of byte strings. A long otherwise. """ wasString=0 if not isinstance(ciphertext, types.TupleType): @@ -79,9 +95,15 @@ integers, MPZ objects, or whatever.""" else: return plaintext def sign(self, M, K): - """sign(M : string|long, K:string|long) : tuple - Return a tuple containing the signature for the message M. - K is a random parameter required by some algorithms. + """Sign a piece of data. + + :Parameter M: The piece of data to encrypt. + :Type M: byte string or long + + :Parameter K: A random parameter required by some algorithms + :Type K: byte string or long + + :Return: A tuple with two items. """ if (not self.has_private()): raise TypeError('Private key not available in this object') @@ -90,9 +112,15 @@ integers, MPZ objects, or whatever.""" return self._sign(M, K) def verify (self, M, signature): - """verify(M:string|long, signature:tuple) : bool - Verify that the signature is valid for the message M; - returns true if the signature checks out. + """Verify the validity of a signature. + + :Parameter M: The expected message. + :Type M: byte string or long + + :Parameter signature: The signature to verify. + :Type signature: tuple with two items, as return by `sign` + + :Return: True if the signature is correct, False otherwise. """ if isinstance(M, types.StringType): M=bytes_to_long(M) return self._verify(M, signature) @@ -103,8 +131,15 @@ integers, MPZ objects, or whatever.""" DeprecationWarning) def blind(self, M, B): - """blind(M : string|long, B : string|long) : string|long - Blind message M using blinding factor B. + """Blind a message to prevent certain side-channel attacks. + + :Parameter M: The message to blind. + :Type M: byte string or long + + :Parameter B: Blinding factor. + :Type B: byte string or long + + :Return: A byte string if M was so. A long otherwise. """ wasString=0 if isinstance(M, types.StringType): @@ -115,8 +150,13 @@ integers, MPZ objects, or whatever.""" else: return blindedmessage def unblind(self, M, B): - """unblind(M : string|long, B : string|long) : string|long - Unblind message M using blinding factor B. + """Unblind a message after cryptographic processing. + + :Parameter M: The encoded message to unblind. + :Type M: byte string or long + + :Parameter B: Blinding factor. + :Type B: byte string or long """ wasString=0 if isinstance(M, types.StringType): @@ -131,29 +171,35 @@ integers, MPZ objects, or whatever.""" # signature-only algorithms. They both return Boolean values # recording whether this key's algorithm can sign and encrypt. def can_sign (self): - """can_sign() : bool - Return a Boolean value recording whether this algorithm can - generate signatures. (This does not imply that this - particular key object has the private information required to - to generate a signature.) + """Tell if the algorithm can deal with cryptographic signatures. + + This property concerns the *algorithm*, not the key itself. + It may happen that this particular key object hasn't got + the private information required to generate a signature. + + :Return: boolean """ return 1 def can_encrypt (self): - """can_encrypt() : bool - Return a Boolean value recording whether this algorithm can - encrypt data. (This does not imply that this - particular key object has the private information required to - to decrypt a message.) + """Tell if the algorithm can deal with data encryption. + + This property concerns the *algorithm*, not the key itself. + It may happen that this particular key object hasn't got + the private information required to decrypt data. + + :Return: boolean """ return 1 def can_blind (self): - """can_blind() : bool - Return a Boolean value recording whether this algorithm can - blind data. (This does not imply that this - particular key object has the private information required to - to blind a message.) + """Tell if the algorithm can deal with data blinding. + + This property concerns the *algorithm*, not the key itself. + It may happen that this particular key object hasn't got + the private information required carry out blinding. + + :Return: boolean """ return 0 @@ -161,21 +207,23 @@ integers, MPZ objects, or whatever.""" # subclasses. def size (self): - """size() : int - Return the maximum number of bits that can be handled by this key. + """Tell the maximum number of bits that can be handled by this key. + + :Return: int """ return 0 def has_private (self): - """has_private() : bool - Return a Boolean denoting whether the object contains - private components. + """Tell if the key object contains private components. + + :Return: bool """ return 0 def publickey (self): - """publickey(): object - Return a new key object containing only the public information. + """Construct a new key carrying only the public information. + + :Return: A new `pubkey` object. """ return self |