o
    Þý°j·!  ã                   @   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
    )Ú
exact_bitsÚrandfuncé   é   ©Úmin_inclusiveÚmax_exclusiver   )r   r   r   )
r   r   ÚpÚpowr
   Úrandom_rangeÚgÚinverseÚxÚy)Úbitsr   ÚobjÚqÚginv© r   ú�/root/aizidognhua/tmp/workspace/projects/ec89d86c-575f-41c9-af57-ac45cbdbf775/venv/lib/python3.10/site-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ÚfieldÚ	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   r0   )r.   r1   ÚrÚa_blindÚaxÚ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   r6   r   zBad K value: GCD(K,p-1)!=1r   )r7   r8   r   r
   Úgcdr"   r   r   r   r   r0   )r.   r1   r2   Úp1r3   Útr4   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.   r1   Ú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   )r7   ©r.   r   r   r   Úhas_privateá   s   
zElGamalKey.has_privatec                 C   ó   dS ©NTr   rI   r   r   r   Úcan_encrypté   ó   zElGamalKey.can_encryptc                 C   rK   rL   r   rI   r   r   r   Úcan_signì   rN   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   rI   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)ÚboolrJ   r$   ÚgetattrÚkey)r.   ÚotherÚresultÚcompr   r   r   Ú__eq__÷   s   
ÿzElGamalKey.__eq__c                 C   s   |   |¡ S r*   )rW   )r.   rT   r   r   r   Ú__ne__  s   zElGamalKey.__ne__c                 C   s   ddl m} |‚)Nr   )ÚPicklingError)ÚpicklerY   )r.   rY   r   r   r   Ú__getstate__  s   zElGamalKey.__getstate__c                 C   ó   t ‚r*   ©ÚNotImplementedError)r.   r1   r2   r   r   r   Úsign  rN   zElGamalKey.signc                 C   r\   r*   r]   )r.   r1   Ú	signaturer   r   r   Úverify  rN   zElGamalKey.verifyc                 C   r\   r*   r]   )r.   r=   r2   r   r   r   Úencrypt  rN   zElGamalKey.encryptc                 C   r\   r*   r]   )r.   Ú
ciphertextr   r   r   Údecrypt  rN   zElGamalKey.decryptc                 C   r\   r*   r]   ©r.   r1   ÚBr   r   r   Úblind  rN   zElGamalKey.blindc                 C   r\   r*   r]   re   r   r   r   Úunblind  rN   zElGamalKey.unblindc                 C   r\   r*   r]   rI   r   r   r   Úsize  rN   zElGamalKey.sizer*   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r$   r/   r5   r>   rB   rH   rJ   rM   rO   rP   rW   rX   r[   r_   ra   rb   rd   rg   rh   ri   r   r   r   r   r   ”   s,    

r   N)Ú__all__Ú
Cryptodomer   ÚCryptodome.Math.Primalityr   r   r   ÚCryptodome.Math.Numbersr
   r   r   Úobjectr   r   r   r   r   Ú<module>   s   >4