U
    Š¾úg²#  ã                   @   sh   d dl mZ d dlmZ d dlmZmZ d dlmZ	 dd„ Z
dd„ ZG d	d
„ d
eƒZG dd„ deƒZdS )é    )Úis_native_int)Únumber)Úlong_to_bytesÚbytes_to_long)Úget_random_bytesc                 C   s@   || kr||  } }d}|r<|d@ r*|| N }| dK } |dL }q|S )z!Multiply two polynomials in GF(2)r   é   © )Úf1Úf2Úzr   r   úE/tmp/pip-unpacked-wheel-_q8s9isk/Cryptodome/Protocol/SecretSharing.pyÚ	_mult_gf2(   s    

r   c                 C   sb   | |k rd| fS t j}d}| }||ƒ}||ƒ|krZd||ƒ| > }||N }|t||ƒN }q&||fS )z˜
    Compute division of polynomials over GF(2).
    Given a and b, it finds two polynomials q and r such that:

    a = b*q + r with deg(r)<deg(b)
    r   r   )r   Úsizer   )ÚaÚbÚdegÚqÚrÚdÚsr   r   r   Ú_div_gf27   s    r   c                   @   s\   e Zd Z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S )Ú_ElementzElement of GF(2^128) fieldé‡   é   é€   c                 C   s4   t |ƒr|| _n t|ƒdkr(t|ƒ| _ntdƒ‚dS )zïInitialize the element to a certain value.

        The value passed as parameter is internally encoded as
        a 128-bit integer, where each bit represents a polynomial
        coefficient. The LSB is the constant coefficient.
        é   z8The encoded value must be an integer or a 16 byte stringN)r   Ú_valueÚlenr   Ú
ValueError)ÚselfZencoded_valuer   r   r   Ú__init__T   s
    z_Element.__init__c                 C   s   | j |j kS ©N©r   )r   Úotherr   r   r   Ú__eq__c   s    z_Element.__eq__c                 C   s   | j S )z7Return the field element, encoded as a 128-bit integer.r"   ©r   r   r   r   Ú__int__f   s    z_Element.__int__c                 C   s   t | jdƒS )z6Return the field element, encoded as a 16 byte string.r   )r   r   r%   r   r   r   Úencodej   s    z_Element.encodec           	      C   sâ   | j }|j }||kr|| }}| j||fkr4tdƒS dd }|d }}|rÚtt|d@ ƒdd … d dd}|||A @ || d |@ B }|dK }tt|d? d@ ƒdd … d dd}||| jA @ || d |@ B }|dL }qFt|ƒS )Nr   r   r   r   )Úbase)r   Úirr_polyr   ÚintÚbin)	r   Zfactorr	   r
   Zmask1Úvr   Zmask2Zmask3r   r   r   Ú__mul__n   s     

 $
z_Element.__mul__c                 C   s   t | j|jA ƒS r!   )r   r   )r   Ztermr   r   r   Ú__add__‡   s    z_Element.__add__c                 C   sp   | j dkrtdƒ‚| j | j }}d\}}|dkrht||ƒd }||t||ƒA  }}||t||ƒA  }}q(t|ƒS )z0Return the inverse of this element in GF(2^128).r   zInversion of zero)r   r   )r   r   r)   r   r   r   )r   Zr0Zr1Ús0Ús1r   r   r   r   ÚinverseŠ   s    
z_Element.inversec                 C   s(   t | jƒ}t|d ƒD ]}||  }q|S )Nr   )r   r   Úrange)r   ÚexponentÚresultÚ_r   r   r   Ú__pow__›   s    

z_Element.__pow__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r)   r    r$   r&   r'   r-   r.   r1   r6   r   r   r   r   r   M   s   r   c                   @   s,   e Zd ZdZeddd„ƒZed	dd„ƒZdS )
ÚShamirz›Shamir's secret sharing scheme.

    A secret is split into ``n`` shares, and it is sufficient to collect
    ``k`` of them to reconstruct the secret.
    Fc                    sL   dd„ t | d ƒD ƒ‰ ˆ  t|ƒ¡ dd„ ‰‡ ‡‡fdd„t d|d ƒD ƒS )a½  Split a secret into ``n`` shares.

        The secret can be reconstructed later using just ``k`` shares
        out of the original ``n``.
        Each share must be kept confidential to the person it was
        assigned to.

        Each share is associated to an index (starting from 1).

        Args:
          k (integer):
            The number of shares needed to reconstruct the secret.
          n (integer):
            The number of shares to create (at least ``k``).
          secret (byte string):
            A byte string of 16 bytes (e.g. an AES 128 key).
          ssss (bool):
            If ``True``, the shares can be used with the ``ssss`` utility
            (without using the "diffusion layer").
            Default: ``False``.

        Return (tuples):
            ``n`` tuples, one per participant.
            A tuple contains two items:

            1. the unique index (an integer)
            2. the share (16 bytes)
        c                 S   s   g | ]}t td ƒƒ‘qS )r   )r   Úrng©Ú.0Úir   r   r   Ú
<listcomp>Ð   s     z Shamir.split.<locals>.<listcomp>r   c                 S   sF   t | ƒ}t dƒ}|D ]}|| | }q|r>|t | ƒt|ƒ 7 }| ¡ S )Nr   )r   r   r'   )ÚuserÚcoeffsÚssssÚidxZshareZcoeffr   r   r   Ú
make_shareÖ   s    z Shamir.split.<locals>.make_sharec                    s   g | ]}|ˆ|ˆ ˆƒf‘qS r   r   r=   ©rB   rE   rC   r   r   r@   ç   s     )r2   Úappendr   )ÚkÚnÚsecretrC   r   rF   r   Úsplit©   s    'zShamir.splitc                    sî   t | ƒ}g }| D ]X}t|d ƒ‰ t|d ƒ}t‡ fdd„|D ƒƒrJtdƒ‚|rZ|ˆ | 7 }| ˆ |f¡ qtdƒ}t|ƒD ]j}|| \}}	tdƒ}
tdƒ}t|ƒD ],}|| d }||kr¢|
|9 }
||| 9 }q¢||	|
 | ¡  7 }qz| ¡ S )a’  Recombine a secret, if enough shares are presented.

        Args:
          shares (tuples):
            The *k* tuples, each containing the index (an integer) and
            the share (a byte string, 16 bytes long) that were assigned to
            a participant.

            .. note::

                Pass exactly as many share as they are required,
                and no more.

          ssss (bool):
            If ``True``, the shares were produced by the ``ssss`` utility
            (without using the "diffusion layer").
            Default: ``False``.

        Return:
            The original secret, as a byte string (16 bytes long).
        r   r   c                 3   s   | ]}|d  ˆ kV  qdS )r   Nr   )r>   Úy©rD   r   r   Ú	<genexpr>  s     z!Shamir.combine.<locals>.<genexpr>zDuplicate share)r   r   Úanyr   rG   r2   r1   r'   )ZsharesrC   rH   Z	gf_sharesÚxÚvaluer4   ÚjZx_jZy_jÚ	numeratorÚdenominatorÚmZx_mr   rM   r   Úcombineé   s,    &zShamir.combineN)F)F)r7   r8   r9   r:   ÚstaticmethodrK   rV   r   r   r   r   r;   ¢   s
   ?r;   N)ZCryptodome.Util.py3compatr   ZCryptodome.Utilr   ZCryptodome.Util.numberr   r   ZCryptodome.Randomr   r<   r   r   Úobjectr   r;   r   r   r   r   Ú<module>"   s   U