Current File : //usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyo
�
Bd\Rc@s�dZdZddddgZddlTddlmZdefd	��YZd
d
�Z	d�Z
defd��YZeZ
d
S(sPElGamal public-key algorithm (randomized encryption and signature).

Signature algorithm
-------------------
The security of the ElGamal signature scheme is based (like DSA) on the discrete
logarithm problem (DLP_). Given a cyclic group, a generator *g*,
and an element *h*, it is hard to find an integer *x* such that *g^x = h*.

The group is the largest multiplicative sub-group of the integers modulo *p*,
with *p* prime.
The signer holds a value *x* (*0<x<p-1*) as private key, and its public
key (*y* where *y=g^x mod p*) is distributed.

The ElGamal signature is twice as big as *p*.

Encryption algorithm
--------------------
The security of the ElGamal encryption scheme is based on the computational
Diffie-Hellman problem (CDH_). Given a cyclic group, a generator *g*,
and two integers *a* and *b*, it is difficult to find
the element *g^{ab}* when only *g^a* and *g^b* are known, and not *a* and *b*. 

As before, the group is the largest multiplicative sub-group of the integers
modulo *p*, with *p* prime.
The receiver holds a value *a* (*0<a<p-1*) as private key, and its public key
(*b* where *b*=g^a*) is given to the sender.

The ElGamal ciphertext is twice as big as *p*.

Domain parameters
-----------------
For both signature and encryption schemes, the values *(p,g)* are called
*domain parameters*.
They are not sensitive but must be distributed to all parties (senders and
receivers).
Different signers can share the same domain parameters, as can
different recipients of encrypted messages.

Security
--------
Both DLP and CDH problem are believed to be difficult, and they have been proved
such (and therefore secure) for more than 30 years.

The cryptographic strength is linked to the magnitude of *p*.
In 2012, a sufficient size for *p* is deemed to be 2048 bits.
For more information, see the most recent ECRYPT_ report.

Even though ElGamal algorithms are in theory reasonably secure for new designs,
in practice there are no real good reasons for using them.
The signature is four times larger than the equivalent DSA, and the ciphertext
is two times larger than the equivalent RSA.

Functionality
-------------
This module provides facilities for generating new ElGamal keys and for constructing
them from known components. ElGamal keys allows you to perform basic signing,
verification, encryption, and decryption.

    >>> from Crypto import Random
    >>> from Crypto.Random import random
    >>> from Crypto.PublicKey import ElGamal
    >>> from Crypto.Util.number import GCD
    >>> from Crypto.Hash import SHA
    >>>
    >>> message = "Hello"
    >>> key = ElGamal.generate(1024, Random.new().read)
    >>> h = SHA.new(message).digest()
    >>> while 1:
    >>>     k = random.StrongRandom().randint(1,key.p-1)
    >>>     if GCD(k,key.p-1)==1: break
    >>> sig = key.sign(h,k)
    >>> ...
    >>> if key.verify(h,sig):
    >>>     print "OK"
    >>> else:
    >>>     print "Incorrect signature"

.. _DLP: http://www.cosic.esat.kuleuven.be/publications/talk-78.pdf
.. _CDH: http://en.wikipedia.org/wiki/Computational_Diffie%E2%80%93Hellman_assumption
.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
s$Id$tgeneratet	constructterrort
ElGamalobji����(t*(tnumbercBseZRS((t__name__t
__module__(((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyRsscCs�t�}|r|d�nxItt|d|��}d|d|_tj|jd|�rPqq|r{|d�nx�tjd|j|�|_d}t|jd|j�dkr�d}n|r�t|j||j�dkr�d}n|r%t	|jd|j�ddkr%d}ntj
|j|j�}|rlt	|jd|�ddkrld}n|r~Pq~q~|r�|d�ntjd|jd|�|_|r�|d	�nt|j|j|j�|_|S(
s'Randomly generate a fresh, new ElGamal key.

    The key will be safe for use for both encryption and signature
    (although it should be used for **only one** purpose).

    :Parameters:
        bits : int
            Key length, or size (in bits) of the modulus *p*.
            Recommended value is 2048.
        randfunc : callable
            Random number generation function; it should accept
            a single integer N and return a string of random data
            N bytes long.
        progress_func : callable
            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.

    :attention: You should always use a cryptographically secure random number generator,
        such as the one defined in the ``Crypto.Random`` module; **don't** just use the
        current time and the ``random`` module.

    :Return: An ElGamal key object (`ElGamalobj`).
    sp
iitrandfuncsg
iisx
sy
(
RtbignumtgetPrimetpRtisPrimetgetRandomRangetgtpowtdivmodtinversetxty(tbitsRt
progress_functobjtqtsafetginv((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyRws>	

	$	)	&	

cCslt�}t|�dkr*td��nx;tt|��D]'}|j|}t||||�q=W|S(s*Construct an ElGamal key from a tuple of valid ElGamal components.

    The modulus *p* must be a prime.

    The following conditions must apply:

    - 1 < g < p-1
    - g^{p-1} = 1 mod p
    - 1 < x < p-1
    - g^x = y mod p

    :Parameters:
        tup : tuple
            A tuple of long integers, with 3 or 4 items
            in the following order:

            1. Modulus (*p*).
            2. Generator (*g*).
            3. Public key (*y*).
            4. Private key (*x*). Optional.

    :Return: An ElGamal key object (`ElGamalobj`).
    iis%argument for construct() wrong length(ii(Rtlent
ValueErrortrangetkeydatatsetattr(ttupRtitfield((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyR�s	
cBs�eZdZddddgZd�Zd�Zd�Zd�Zd	�Zd
�Z	d�Z
d�Zd
�Zd�Z
d�ZRS(siClass defining an ElGamal key.

    :undocumented: __getstate__, __setstate__, __repr__, __getattr__
    RRRRcCstj|||�S(sREncrypt a piece of data with ElGamal.

        :Parameter plaintext: The piece of data to encrypt with ElGamal.
         It must be numerically smaller than the module (*p*).
        :Type plaintext: byte string or long

        :Parameter K: A secret number, chosen randomly in the closed
         range *[1,p-2]*.
        :Type K: long (recommended) or byte string (not recommended)

        :Return: A tuple with two items. Each item is of the same type as the
         plaintext (string or long).

        :attention: selection of *K* is crucial for security. Generating a
         random number larger than *p-1* and taking the modulus by *p-1* is
         **not** secure, since smaller values will occur more frequently.
         Generating a random number systematically smaller than *p-1*
         (e.g. *floor((p-1)/8)* random bytes) is also **not** secure.
         In general, it shall not be possible for an attacker to know
         the value of any bit of K.

        :attention: The number *K* shall not be reused for any other
         operation and shall be discarded immediately.
        (tpubkeytencrypt(tselft	plaintexttK((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyR#�scCstj||�S(sPDecrypt a piece of data with ElGamal.

        :Parameter ciphertext: The piece of data to decrypt with ElGamal.
        :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.
        (R"tdecrypt(R$t
ciphertext((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyR's
cCstj|||�S(s�Sign a piece of data with ElGamal.

        :Parameter M: The piece of data to sign with ElGamal. It may
         not be longer in bit size than *p-1*.
        :Type M: byte string or long

        :Parameter K: A secret number, chosen randomly in the closed
         range *[1,p-2]* and such that *gcd(k,p-1)=1*.
        :Type K: long (recommended) or byte string (not recommended)

        :attention: selection of *K* is crucial for security. Generating a
         random number larger than *p-1* and taking the modulus by *p-1* is
         **not** secure, since smaller values will occur more frequently.
         Generating a random number systematically smaller than *p-1*
         (e.g. *floor((p-1)/8)* random bytes) is also **not** secure.
         In general, it shall not be possible for an attacker to know
         the value of any bit of K.

        :attention: The number *K* shall not be reused for any other
         operation and shall be discarded immediately.

        :attention: M must be be a cryptographic hash, otherwise an
         attacker may mount an existential forgery attack.

        :Return: A tuple with 2 longs.
        (R"tsign(R$tMR&((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyR)scCstj|||�S(sNVerify the validity of an ElGamal signature.

        :Parameter M: The expected message.
        :Type M: byte string or long

        :Parameter signature: The ElGamal signature to verify.
        :Type signature: A tuple with 2 longs as return by `sign`

        :Return: True if the signature is correct, False otherwise.
        (R"tverify(R$R*t	signature((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyR+9scCsEt|j||j�}|t|j||j�|j}||fS(N(RRRR(R$R*R&tatb((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyt_encryptFs#cCs_t|d�std��nt|d|j|j�}|dt||j�|j}|S(NRs(Private key not available in this objectii(thasattrt	TypeErrorRRRR(R$R*taxR%((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyt_decryptKs
!cCs�t|d�std��n|jd}t||�dkrOtd��nt|j||j�}||j||}x|dkr�||}qW|t||�|}||fS(NRs(Private key not available in this objectisBad K value: GCD(K,p-1)!=1i(	R0R1RtGCDRRRRR(R$R*R&tp1R-ttR.((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyt_signRs
cCs�|ddks'|d|jdkr+dSt|j|d|j�}|t|d|d|j�|j}t|j||j�}||kr�dSdS(Nii(RRRR(R$R*tsigtv1tv2((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyt_verify^s'(cCstj|j�dS(Ni(RtsizeR(R$((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyR<hscCst|d�rdSdSdS(NRii(R0(R$((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pythas_privatekscCst|j|j|jf�S(N(RRRR(R$((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyt	publickeyqs(RRt__doc__RR#R'R)R+R/R3R7R;R<R=R>(((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyR�s
				
				
		N(R?t__revision__t__all__tCrypto.PublicKey.pubkeytCrypto.UtilRt	ExceptionRtNoneRRR"Rtobject(((s>/usr/lib64/python2.7/site-packages/Crypto/PublicKey/ElGamal.pyt<module>js
J	!�