U
    g!                     @   sZ   d ddgZ ddlmZ ddlmZmZmZ ddlmZ dd  Z	dd Z
G d	d deZd
S )generate	construct
ElGamalKey    )Random)generate_probable_safe_primetest_probable_prime	COMPOSITEIntegerc                 C   s   t  }t| |d|_|jd d? }ttjd|j|dd|j|_|jdkrLq"|jd |j dkrbq"|j|j}|jd | dkrq"qq"tjd|jd |d|_t|j|j|j|_	|S )a  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).

    Args:
      bits (int):
        Key length, or size (in bits) of the modulus *p*.
        The recommended value is 2048.
      randfunc (callable):
        Random number generation function; it should accept
        a single integer *N* and return a string of random
        *N* random bytes.

    Return:
        an :class:`ElGamalKey` object
    )Z
exact_bitsrandfunc      Zmin_inclusiveZmax_exclusiver   )r   r   r   )
r   r   ppowr
   random_rangeginversexy)bitsr   objqZginv r   @/tmp/pip-unpacked-wheel-_q8s9isk/Cryptodome/PublicKey/ElGamal.pyr   "   s0     
c                 C   s   t  }t| dkrtdtt| D ]"}|j| }t||t| |  q&t|jt	k}||j
dkpn|j
|jkO }|t|j
|jd |jdkO }||jdk p|j|jkO }t| dkr||jdkp|j|jkO }|t|j
|j|j|jkO }|rtd|S )a  Construct an ElGamal key from a tuple of valid ElGamal components.

    The modulus *p* must be a prime.
    The following conditions must apply:

    .. math::

        \begin{align}
        &1 < g < p-1 \\
        &g^{p-1} = 1 \text{ mod } 1 \\
        &1 < x < p-1 \\
        &g^x = y \text{ mod } p
        \end{align}

    Args:
      tup (tuple):
        A tuple with either 3 or 4 integers,
        in the following order:

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

    Raises:
        ValueError: when the key being imported fails the most basic ElGamal validity checks.

    Returns:
        an :class:`ElGamalKey` object
    )      z%argument for construct() wrong lengthr   r   zInvalid ElGamal key components)r   len
ValueErrorrange_keydatasetattrr
   r   r   r   r   r   r   r   )tupr   ifieldZ	fmt_errorr   r   r   r   `   s      
c                   @   s   e Zd ZdZddddgZd-ddZd	d
 Zdd Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, ZdS ).r   aP  Class defining an ElGamal key.
    Do not instantiate directly.
    Use :func:`generate` or :func:`construct` instead.

    :ivar p: Modulus
    :vartype d: integer

    :ivar g: Generator
    :vartype e: integer

    :ivar y: Public key component
    :vartype y: integer

    :ivar x: Private key component
    :vartype x: integer
    r   r   r   r   Nc                 C   s   |d krt  j}|| _d S N)r   newread	_randfunc)selfr   r   r   r   __init__   s    
zElGamalKey.__init__c                 C   s:   t | j|| j}t | j|| j| | j }t|t|gS r%   )r   r   r   r   int)r)   MKabr   r   r   _encrypt   s    zElGamalKey._encryptc                 C   s   t | dstdtjd| jd | jd}t| j|| j|d  | j }t|| j| j}|	| j|d  | j }|t| j
|| j | j }t|S )Nr   (Private key not available in this objectr   r   r   r   )hasattr	TypeErrorr
   r   r   r(   r   r   r   r   r   r+   )r)   r,   rZa_blindZaxZplaintext_blind	plaintextr   r   r   _decrypt   s    
zElGamalKey._decryptc                 C   s   t | dstd| jd }t|}||dkr:tdt| j|| j}t|| j|  | }|dk rr|| }q`||	| | }t
|t
|gS )Nr   r1   r   zBad K value: GCD(K,p-1)!=1r   )r2   r3   r   r
   gcdr   r   r   r   r   r+   )r)   r,   r-   p1r.   tr/   r   r   r   _sign   s    

 
zElGamalKey._signc                 C   s   dd |D }|d dk s,|d | j d kr0dS t| j|d | j }|t|d |d | j  | j  }t| j|| j }||krdS dS )Nc                 S   s   g | ]}t |qS r   r	   ).0r   r   r   r   
<listcomp>   s     z&ElGamalKey._verify.<locals>.<listcomp>r   r   )r   r   r   r   )r)   r,   sigZv1Zv2r   r   r   _verify   s     zElGamalKey._verifyc                 C   s   t | drdS dS dS )z&Whether this is an ElGamal private keyr   r   r   N)r2   r)   r   r   r   has_private   s    
zElGamalKey.has_privatec                 C   s   dS NTr   r?   r   r   r   can_encrypt   s    zElGamalKey.can_encryptc                 C   s   dS rA   r   r?   r   r   r   can_sign   s    zElGamalKey.can_signc                 C   s   t | j| j| jfS )zfA matching ElGamal public key.

        Returns:
            a new :class:`ElGamalKey` object
        )r   r   r   r   r?   r   r   r   	publickey   s    zElGamalKey.publickeyc                 C   sP   t |  t | krdS d}| jD ]$}|oHt| j|d t|j|d k}q&|S )NFT)boolr@   r    getattrkey)r)   otherresultcompr   r   r   __eq__   s    
zElGamalKey.__eq__c                 C   s   |  | S r%   )rK   )r)   rH   r   r   r   __ne__  s    zElGamalKey.__ne__c                 C   s   ddl m} |d S )Nr   )PicklingError)picklerM   )r)   rM   r   r   r   __getstate__  s    zElGamalKey.__getstate__c                 C   s   t d S r%   NotImplementedError)r)   r,   r-   r   r   r   sign  s    zElGamalKey.signc                 C   s   t d S r%   rP   )r)   r,   	signaturer   r   r   verify  s    zElGamalKey.verifyc                 C   s   t d S r%   rP   )r)   r5   r-   r   r   r   encrypt  s    zElGamalKey.encryptc                 C   s   t d S r%   rP   )r)   Z
ciphertextr   r   r   decrypt  s    zElGamalKey.decryptc                 C   s   t d S r%   rP   r)   r,   Br   r   r   blind  s    zElGamalKey.blindc                 C   s   t d S r%   rP   rW   r   r   r   unblind  s    zElGamalKey.unblindc                 C   s   t d S r%   rP   r?   r   r   r   size  s    zElGamalKey.size)N)__name__
__module____qualname____doc__r    r*   r0   r6   r:   r>   r@   rB   rC   rD   rK   rL   rO   rR   rT   rU   rV   rY   rZ   r[   r   r   r   r   r      s*   

N)__all__Z
Cryptodomer   ZCryptodome.Math.Primalityr   r   r   ZCryptodome.Math.Numbersr
   r   r   objectr   r   r   r   r   <module>   s   
>4