diff options
author | akuchling <akuchling@rivest.dlitz.net> | 2002-05-12 23:39:07 -0700 |
---|---|---|
committer | akuchling <akuchling@rivest.dlitz.net> | 2002-05-12 23:39:07 -0700 |
commit | 432406a2c11296100df3ba848a509d6efb10a61d (patch) | |
tree | 6b3e6fcff4a2eb54fe228e6220ac8abf79204a49 /Doc | |
parent | 2fcc7796c2489ef94016e51269bf9f19a4073142 (diff) | |
download | pycrypto-432406a2c11296100df3ba848a509d6efb10a61d.tar.gz |
[project @ akuchling-20020513063907-d0ccf4cffe4846c7]
[project @ 2002-05-12 23:39:07 by akuchling]
Restore PublicKey docs
Diffstat (limited to 'Doc')
-rw-r--r-- | Doc/pycrypt.tex | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/Doc/pycrypt.tex b/Doc/pycrypt.tex index 5bee569..030ae27 100644 --- a/Doc/pycrypt.tex +++ b/Doc/pycrypt.tex @@ -644,6 +644,228 @@ that can be used to discern it from wheat data without running the MAC. \end{methoddesc} +\section{Crypto.PublicKey: Public Key Algorithms} +So far, the encryption algorithms described have all been \dfn{private +key} ciphers. That is, the same key is used for both encryption and +decryption, so all correspondents must know it. This poses a problem: +you may want encryption to communicate sensitive data over an insecure +channel, but how can you tell your correspondent what the key is? You +can't just e-mail it to her because the channel is insecure. One +solution is to arrange the key via some other way: over the phone or +by meeting in person. + +Another solution is to use \dfn{public key} cryptography. In a public +key system, there are two different keys: one for encryption and one for +decryption. The encryption key can be made public by listing it in a +directory or mailing it to your correspondent, while you keep the +decryption key secret. Your correspondent then sends you data encrypted +with your public key, and you use the private key to decrypt it. While +the two keys are related, it's very difficult to derive the private key +given only the public key; however, deriving the private key is always +possible given enough time and computing power. This makes it very +important to pick keys of the right size: large enough to be secure, but +small enough to be applied fairly quickly. + +Many public key algorithms can also be used to sign messages; simply +run the message to be signed through a decryption with your private +key key. Anyone receiving the message can encrypt it with your +publicly available key and read the message. Some algorithms do only +one thing, others can both encrypt and authenticate. + +The currently available public key algorithms are listed in the +following table: + +\begin{tableii}{c|l}{}{Algorithm}{Capabilities} +\lineii{RSA}{Encryption, authentication/signatures} +\lineii{ElGamal}{Encryption, authentication/signatures} +\lineii{DSA}{Authentication/signatures} +\lineii{qNEW}{Authentication/signatures} +\end{tableii} + +Many of these algorithms are patented. Before using any of them in a +commercial product, consult a patent attorney; you may have to arrange +a license with the patent holder. + +An example of using the RSA module to sign a message: +\begin{verbatim} +>>> from Crypto.Hash import MD5 +>>> from Crypto.PublicKey import RSA +>>> RSAkey=RSA.generate(384, randfunc) # This will take a while... +>>> hash=MD5.new(plaintext).digest() +>>> signature=RSAkey.sign(hash, "") +>>> signature # Print what an RSA sig looks like--you don't really care. +('\021\317\313\336\264\315' ...,) +>>> RSAkey.verify(hash, signature) # This sig will check out +1 +>>> RSAkey.verify(hash[:-1], signature)# This sig will fail +0 +\end{verbatim} + + +Public key modules make the following functions available: + +\begin{funcdesc}{construct}{tuple} +Constructs a key object from a tuple of data. This is +algorithm-specific; look at the source code for the details. (To be +documented later.) +\end{funcdesc} + +\begin{funcdesc}{generate}{size, randfunc, progress_func=\code{None}} +Generate a fresh public/private key pair. \var{size} is a +algorithm-dependent size parameter; the larger it is, the more +difficult it will be to break the key. Safe key sizes vary from +algorithm to algorithm; you'll have to research the question and +decide on a suitable key size for your application. \code{randfunc} +is a random number generation function; it should accept a single +integer \var{N} and return a string of random data \var{N} bytes long. +You should always use a cryptographically secure random number +generator, such as the one defined in the \code{randpool} module; +\emph{don't} just use the current time and the \code{whrandom} module. + +\var{progress_func} is an optional function that will be called with a short +string containing the key parameter currently being generated; it's +useful for interactive applications where a user is waiting for a key to +be generated. +\end{funcdesc} + +If you want to interface with some other program, you will have to know +the details of the algorithm being used; this isn't a big loss. If you +don't care about working with non-Python software, simply use the +\code{pickle} module when you need to write a key or a signature to a +file. It's portable across all the architectures that Python supports, +and it's simple to use. + +Public key objects always support the following methods. Some of them +may raise exceptions if their functionality is not supported by the +algorithm. + +\begin{funcdesc}{canencrypt}{} +Returns true if the algorithm is capable of encrypting and decrypting +data; returns false otherwise. To test if a given key object can sign +data, use \code{key.canencrypt() and key.hasprivate()}. +\end{funcdesc} + +\begin{funcdesc}{cansign}{} +Returns true if the algorithm is capable of signing data; returns false +otherwise. To test if a given key object can sign data, use +\code{key.cansign() and key.hasprivate()}. +\end{funcdesc} + +\begin{funcdesc}{decrypt}{tuple} +Decrypts \var{tuple} with the private key, returning another string. +This requires the private key to be present, and will raise an exception +if it isn't present. It will also raise an exception if \var{string} is +too long. +\end{funcdesc} + +\begin{funcdesc}{encrypt}{string, K} +Encrypts \var{string} with the private key, returning a tuple of +strings; the length of the tuple varies from algorithm to algorithm. +\var{K} should be a string of random data that is as long as +possible. Encryption does not require the private key to be present +inside the key object. It will raise an exception if \var{string} is +too long. For ElGamal objects, the value of \var{K} expressed as a +big-endian integer must be relatively prime to \code{self.p-1}; an +exception is raised if it is not. +\end{funcdesc} + +\begin{funcdesc}{hasprivate}{} +Returns true if the key object contains the private key data, which +will allow decrypting data and generating signatures. +Otherwise this returns false. +\end{funcdesc} + +\begin{funcdesc}{publickey}{} +Returns a new public key object that doesn't contain the private key +data. +\end{funcdesc} + +\begin{funcdesc}{sign}{string, K} +Sign \var{string}, returning a signature, which is just a tuple; in +theory the signature may be made up of any Python objects at all; in +practice they'll be either strings or numbers. \var{K} should be a +string of random data that is as long as possible. Different algorithms +will return tuples of different sizes. \code{sign()} raises an +exception if \var{string} is too long. For ElGamal objects, the value +of \var{K} expressed as a big-endian integer must be relatively prime to +\code{self.p-1}; an exception is raised if it is not. +\end{funcdesc} + +\begin{funcdesc}{size}{} +Returns the maximum size of a string that can be encrypted or signed, +measured in bits. String data is treated in big-endian format; the most +significant byte comes first. (This seems to be a \emph{de facto} standard +for cryptographical software.) If the size is not a multiple of 8, then +some of the high order bits of the first byte must be zero. Usually +it's simplest to just divide the size by 8 and round down. +\end{funcdesc} + +\begin{funcdesc}{verify}{string, signature} +Returns true if the signature is valid, and false otherwise. +\var{string} is not processed in any way; \code{verify} does +not run a hash function over the data, but you can easily do that yourself. +\end{funcdesc} + +\subsection{The ElGamal and DSA algorithms} +For RSA, the \var{K} parameters are unused; if you like, you can just +pass empty strings. The ElGamal and DSA algorithms require a real +\var{K} value for technical reasons; see Schneier's book for a detailed +explanation of the respective algorithms. This presents a possible +hazard that can +inadvertently reveal the private key. Without going into the +mathematical details, the danger is as follows. \var{K} is never derived +or needed by others; theoretically, it can be thrown away once the +encryption or signing operation is performed. However, revealing +\var{K} for a given message would enable others to derive the secret key +data; worse, reusing the same value of \var{K} for two different +messages would also enable someone to derive the secret key data. An +adversary could intercept and store every message, and then try deriving +the secret key from each pair of messages. + +This places implementors on the horns of a dilemma. On the one hand, +you want to store the \var{K} values to avoid reusing one; on the other +hand, storing them means they could fall into the hands of an adversary. +One can randomly generate \var{K} values of a suitable length such as +128 or 144 bits, and then trust that the random number generator +probably won't produce a duplicate anytime soon. This is an +implementation decision that depends on the desired level of security +and the expected usage lifetime of a private key. I cannot choose and +enforce one policy for this, so I've added the \var{K} parameter to the +\code{encrypt} and \code{sign} functions. You must choose \var{K} by +generating a string of random data; for ElGamal, when interpreted as a +big-endian number (with the most significant byte being the first byte +of the string), \var{K} must be relatively prime to \code{self.p-1}; any +size will do, but brute force searches would probably start with small +primes, so it's probably good to choose fairly large numbers. It might be +simplest to generate a prime number of a suitable length using the +\code{Crypto.Util.number} module. + +\subsection{Security Notes for Public-key Algorithms} +Any of these algorithms can be trivially broken; for example, RSA can be +broken by factoring the modulus \emph{n} into its two prime factors. +This is easily done by the following code: + +\begin{verbatim} +for i in range(2, n): + if (n%i)==0: print i, 'is a factor' ; break +\end{verbatim} + + +However, \emph{n} is usually a few hundred bits long, so this simple +program wouldn't find a solution before the universe comes to an end. +Smarter algorithms can factor numbers more quickly, but it's still +possible to choose keys so large that they can't be broken in a +reasonable amount of time. For ElGamal and DSA, discrete logarithms are +used instead of factoring, but the principle is the same. + +Safe key sizes depend on the current state of computer science and +technology. At the moment, one can roughly define three levels of +security: low-security commercial, high-security commercial, and +military-grade. For RSA, these three levels correspond roughly to 512, +768, and 1024 bit-keys. For ElGamal and DSA, the key sizes should be +somewhat larger for the same level of security, around 768, 1024, and +1536 bits. + \section{Crypto.Util: Odds and Ends} This chapter contains all the modules that don't fit into any of the other chapters. |