o
    n~b!                     @   sX   g d 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v r'q|jd |j dkr2q|j|j}|jd | dkrCq	 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   G/usr/local/lib/python3.10/dist-packages/Cryptodome/PublicKey/ElGamal.pyr   "   s0   
r   c                 C   s   t  }t| dvrtdtt| D ]}|j| }t||t| |  qt|jt	k}||j
dkp7|j
|jkO }|t|j
|jd |jdkO }||jdk pS|j|jkO }t| dkrv||jdkpf|j|jkO }|t|j
|j|j|jkO }|r|t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     
r   c                   @   s   e Zd ZdZg d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 u 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_blind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 r<|| }|dk s4||	| | }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rdS t| j|d | j }|t|d |d | j  | j  }t| j|| j }||kr@d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,   sigv1v2r   r   r   _verify   s    zElGamalKey._verifyc                 C   s   t | drdS dS )z&Whether this is an ElGamal private keyr   r   r   )r2   r)   r   r   r   has_private   s   
zElGamalKey.has_privatec                 C      dS NTr   rB   r   r   r   can_encrypt      zElGamalKey.can_encryptc                 C   rD   rE   r   rB   r   r   r   can_sign   rG   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   rB   r   r   r   	publickey   s   zElGamalKey.publickeyc                 C   sP   t |  t | krdS d}| jD ]}|o$t| j|d t|j|d k}q|S )NFT)boolrC   r    getattrkey)r)   otherresultcompr   r   r   __eq__   s   
zElGamalKey.__eq__c                 C   s   |  | S r%   )rP   )r)   rM   r   r   r   __ne__  s   zElGamalKey.__ne__c                 C   s   ddl m} |)Nr   )PicklingError)picklerR   )r)   rR   r   r   r   __getstate__  s   zElGamalKey.__getstate__c                 C      t r%   NotImplementedError)r)   r,   r-   r   r   r   sign  rG   zElGamalKey.signc                 C   rU   r%   rV   )r)   r,   	signaturer   r   r   verify  rG   zElGamalKey.verifyc                 C   rU   r%   rV   )r)   r6   r-   r   r   r   encrypt  rG   zElGamalKey.encryptc                 C   rU   r%   rV   )r)   Z
ciphertextr   r   r   decrypt  rG   zElGamalKey.decryptc                 C   rU   r%   rV   r)   r,   Br   r   r   blind  rG   zElGamalKey.blindc                 C   rU   r%   rV   r]   r   r   r   unblind  rG   zElGamalKey.unblindc                 C   rU   r%   rV   rB   r   r   r   size  rG   zElGamalKey.sizer%   )__name__
__module____qualname____doc__r    r*   r0   r7   r;   rA   rC   rF   rH   rI   rP   rQ   rT   rX   rZ   r[   r\   r_   r`   ra   r   r   r   r   r      s,    

r   N)__all__Z
Cryptodomer   ZCryptodome.Math.Primalityr   r   r   ZCryptodome.Math.Numbersr
   r   r   objectr   r   r   r   r   <module>   s   >4