U
    gW                     @   s"  d dddgZ ddlZddlZddlZddlmZmZmZmZm	Z	 ddl
mZ ddlmZmZ dd	lmZ dd
lmZmZmZmZmZ ddlmZ ddlmZmZmZ ddlmZmZm Z  G dd de!Z"dd Z#d dd Z$d!ddZ%dd Z&dd Z'dd Z(dd Z)dd Z*d"ddZ+e+Z,dZ-dS )#generate	constructDsaKey
import_key    N)bchrbordtobytestostr
iter_range)Random)PKCS8PEM)SHA256)	DerObjectDerSequence
DerIntegerDerObjectIdDerBitString)Integer)test_probable_prime	COMPOSITEPROBABLY_PRIME)_expand_subject_public_key_info_create_subject_public_key_info _extract_subject_public_key_infoc                   @   s   e Zd ZdZdddddg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d3d#d$ZeZeZd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zd"S )4r   a  Class defining an actual DSA key.
    Do not instantiate directly.
    Use :func:`generate`, :func:`construct` or :func:`import_key` instead.

    :ivar p: DSA modulus
    :vartype p: integer

    :ivar q: Order of the subgroup
    :vartype q: integer

    :ivar g: Generator
    :vartype g: integer

    :ivar y: Public key
    :vartype y: integer

    :ivar x: Private key
    :vartype x: integer

    :undocumented: exportKey, publickey
    ygpqxc                 C   sp   t | }t d}||s2tdt||  || }|rb|t dkrbtdt|t d  t|| _d S )Nr   r   r   r   z$Some DSA components are missing = %sr   zUnknown DSA components = %s)setkeysissubset
ValueErrorstrdict_key)selfkey_dictZ	input_setZ
public_setZ	extra_set r+   </tmp/pip-unpacked-wheel-_q8s9isk/Cryptodome/PublicKey/DSA.py__init__g   s    

zDsaKey.__init__c                    s      stdd|  k r& jk s0n td fdddD \}}}}tjd|d}|| |}|| }	t|||| }
||| |	|
   | }tt	|
|fS )Nz)DSA public key cannot be used for signing   zk is not between 2 and q-1c                    s   g | ]} j | qS r+   r(   .0compr)   r+   r,   
<listcomp>y   s     z DsaKey._sign.<locals>.<listcomp>)r   r   r   r   )Zmin_inclusiveZmax_exclusive)
has_private	TypeErrorr   r%   r   Zrandom_rangeinversepowmapint)r)   mkr   r   r   r   Zblind_factorZinv_blind_kZblind_xrsr+   r3   r,   _signs   s    zDsaKey._signc                    s   |\}} fdddD \}}}}d|  k r6|k rPn nd|  k rN|k sTn dS t ||}	|	| | }
|	| | }t||
|t||| | | }||kS )Nc                    s   g | ]} j | qS r+   r/   r0   r3   r+   r,   r4      s     z"DsaKey._verify.<locals>.<listcomp>)r   r   r   r   r   F)r   r7   r8   )r)   r;   sigr=   r>   r   r   r   r   wu1u2vr+   r3   r,   _verify   s    . zDsaKey._verifyc                 C   s
   d| j kS )z!Whether this is a DSA private keyr   r/   r3   r+   r+   r,   r5      s    zDsaKey.has_privatec                 C   s   dS )NFr+   r3   r+   r+   r,   can_encrypt   s    zDsaKey.can_encryptc                 C   s   dS )NTr+   r3   r+   r+   r,   can_sign   s    zDsaKey.can_signc                    s   t  fdddD }t|S )z^A matching DSA public key.

        Returns:
            a new :class:`DsaKey` object
        c                 3   s   | ]}| j | fV  qd S Nr/   )r1   r<   r3   r+   r,   	<genexpr>   s     z$DsaKey.public_key.<locals>.<genexpr>r    )r'   r   )r)   Zpublic_componentsr+   r3   r,   
public_key   s    zDsaKey.public_keyc                 C   sP   t |  t | krdS d}| jD ]$}|oHt| j|d t|j|d k}q&|S )NFT)boolr5   _keydatagetattrr(   )r)   otherresultr2   r+   r+   r,   __eq__   s    
zDsaKey.__eq__c                 C   s   |  | S rH   )rP   )r)   rN   r+   r+   r,   __ne__   s    zDsaKey.__ne__c                 C   s   ddl m} |d S )Nr   )PicklingError)picklerR   )r)   rR   r+   r+   r,   __getstate__   s    zDsaKey.__getstate__c                    s    fdddD S )zPThe DSA domain parameters.

        Returns
            tuple : (p,q,g)
        c                    s   g | ]}t  j| qS r+   )r:   r(   r0   r3   r+   r,   r4      s     z!DsaKey.domain.<locals>.<listcomp>)r   r   r   r+   r3   r+   r3   r,   domain   s    zDsaKey.domainc                 C   sz   g }| j D ]@}|dkr6t| j }|d|f  q
t| |r
|| q
|  r^|d d| jjt	| d
|f S )Nr   zp(%d)privatez<%s @0x%x %s>,)rL   r   r   size_in_bitsappendhasattrr5   	__class____name__idjoin)r)   attrsr<   bitsr+   r+   r,   __repr__   s    


zDsaKey.__repr__c                 C   s2   zt | j| W S  tk
r,   t|Y nX d S rH   )r:   r(   KeyErrorAttributeError)r)   itemr+   r+   r,   __getattr__   s    zDsaKey.__getattr__r   Nc                    s  |dk	rt |}|dkrtj}|dkrfdddD }dd   fdd|D }d	g| }d
dd |D }	dt|	dd  S tjjj	g}

 r8|dkrd}|r|sd}tj }tj|t|||
|d}|rd}nd}d}nB|dkr|rtddjjj	jjg}t| }d}n$|rFtdtttj|
}d}|dkrj|S |dkrt||d ||}t |S td| dS )a  Export this DSA key.

        Args:
          format (string):
            The encoding for the output:

            - *'PEM'* (default). ASCII as per `RFC1421`_/ `RFC1423`_.
            - *'DER'*. Binary ASN.1 encoding.
            - *'OpenSSH'*. ASCII one-liner as per `RFC4253`_.
              Only suitable for public keys, not for private keys.

          passphrase (string):
            *Private keys only*. The pass phrase to protect the output.

          pkcs8 (boolean):
            *Private keys only*. If ``True`` (default), the key is encoded
            with `PKCS#8`_. If ``False``, it is encoded in the custom
            OpenSSL/OpenSSH container.

          protection (string):
            *Only in combination with a pass phrase*.
            The encryption scheme to use to protect the output.

            If :data:`pkcs8` takes value ``True``, this is the PKCS#8
            algorithm to use for deriving the secret and encrypting
            the private DSA key.
            For a complete list of algorithms, see :mod:`Cryptodome.IO.PKCS8`.
            The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*.

            If :data:`pkcs8` is ``False``, the obsolete PEM encryption scheme is
            used. It is based on MD5 for key derivation, and Triple DES for
            encryption. Parameter :data:`protection` is then ignored.

            The combination ``format='DER'`` and ``pkcs8=False`` is not allowed
            if a passphrase is present.

          randfunc (callable):
            A function that returns random bytes.
            By default it is :func:`Cryptodome.Random.get_random_bytes`.

        Returns:
          byte string : the encoded key

        Raises:
          ValueError : when the format is unknown or when you try to encrypt a private
            key with *DER* format and OpenSSL/OpenSSH.

        .. warning::
            If you don't provide a pass phrase, the private key will be
            exported in the clear!

        .. _RFC1421:    http://www.ietf.org/rfc/rfc1421.txt
        .. _RFC1423:    http://www.ietf.org/rfc/rfc1423.txt
        .. _RFC4253:    http://www.ietf.org/rfc/rfc4253.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        NZOpenSSHc                    s   g | ]} j |  qS r+   )r(   to_bytesr1   r   r3   r+   r,   r4     s     z%DsaKey.export_key.<locals>.<listcomp>)r   r   r   r   c                 S   s$   t | d d@ rtd|  S | S d S )Nr      )r   r   r!   r+   r+   r,   func  s    zDsaKey.export_key.<locals>.funcc                    s   g | ]} |qS r+   r+   rg   )ri   r+   r,   r4     s        ssh-dss    c                 S   s    g | ]}t d t|| qS )>I)structpacklen)r1   Zkpr+   r+   r,   r4     s        ssh-dss Tz"PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC)Z
key_paramsrandfunczENCRYPTED PRIVATEZPRIVATEr   z#DSA private key cannot be encryptedr   zDSA PRIVATEz*PKCS#8 is only meaningful for private keysZPUBLICZDERz KEYz3Unknown key format '%s'. Cannot export the DSA key.)r   r   get_random_bytesr^   binascii
b2a_base64r   r   r   r   r5   r   r   encoder   wrapoidr%   r   r   r   )r)   formatZpkcs8
passphraseZ
protectionrr   Ztup1Ztup2keyparts	keystringparamsZprivate_keyZ
binary_keyZkey_typeZintsZpem_strr+   )ri   r)   r,   
export_key   sp    ;

    

  zDsaKey.export_keyc                 C   s   t dd S Nz+Use module Cryptodome.Signature.DSS insteadNotImplementedError)r)   MKr+   r+   r,   signU  s    zDsaKey.signc                 C   s   t dd S r   r   )r)   r   	signaturer+   r+   r,   verifyX  s    zDsaKey.verifyc                 C   s   t d S rH   r   )r)   	plaintextr   r+   r+   r,   encrypt[  s    zDsaKey.encryptc                 C   s   t d S rH   r   )r)   Z
ciphertextr+   r+   r,   decrypt^  s    zDsaKey.decryptc                 C   s   t d S rH   r   r)   r   Br+   r+   r,   blinda  s    zDsaKey.blindc                 C   s   t d S rH   r   r   r+   r+   r,   unblindd  s    zDsaKey.unblindc                 C   s   t d S rH   r   r3   r+   r+   r,   sizeg  s    zDsaKey.size)r   NNNN)r\   
__module____qualname____doc__rL   r-   r?   rE   r5   rF   rG   rJ   rP   rQ   rT   rU   ra   re   r~   Z	exportKeyZ	publickeyr   r   r   r   r   r   r   r+   r+   r+   r,   r   N   s8   

	    
~c                    s  dddd | }|dkr&td|  tjd |  d  d }| d |  }td	}d|d > }t||tkr|d
tt	 |d @ }||B dB }qh|
 |kstdd| d > }fddt|d D  dd  D  t fddt|D  | d|> d @ d| >  }t|| }	|	
 | ksJt|	|d  }
|	|
d  }|
 | krt||tkrq|d 7 q|d | }tdD ]R}d td t|  }tt|	 }t|||}|dkr qq|||fS )z+Generate a new set of DSA domain parameters         )         NzInvalid modulus length (%d)   r.      @   c                    s*   g | ]"}t t |    qS r+   )r   newr   rf   digest)r1   j)offsetseedr+   r,   r4     s   z$_generate_domain.<locals>.<listcomp>c                 S   s   g | ]}t |qS r+   r   
from_bytes)r1   rD   r+   r+   r,   r4     s     c                    s    g | ]} | d | >  qS )r.   r+   )r1   i)Voutlenr+   r,   r4     s        s   ggen)getr%   r   digest_sizer   r   r   r   r   r   rX   AssertionErrorr
   sum	itertoolscountr   rf   r8   )Lrr   NnZb_r   Z	upper_bitUWXcr   er   r   r+   )r   r   r   r   r,   _generate_domaink  sN    



r   c                 C   sB  |dkrt j}|rtt|\}}}t|tk}|t|tkO }||d | dkO }||dkpb||kO }|t|||dkO }|rtdnt| |\}}}}|	 }|	 }	|| krtd|| f ||	fdkrtd||	f d|  k r|k sn tdtj
|	d	 |d
}
|
|d  d }t|||}|||||d}t|S )a  Generate a new DSA key pair.

    The algorithm follows Appendix A.1/A.2 and B.1 of `FIPS 186-4`_,
    respectively for domain generation and key pair generation.

    Args:
      bits (integer):
        Key length, or size (in bits) of the DSA modulus *p*.
        It must be 1024, 2048 or 3072.

      randfunc (callable):
        Random number generation function; it accepts a single integer N
        and return a string of random data N bytes long.
        If not specified, :func:`Cryptodome.Random.get_random_bytes` is used.

      domain (tuple):
        The DSA domain parameters *p*, *q* and *g* as a list of 3
        integers. Size of *p* and *q* must comply to `FIPS 186-4`_.
        If not specified, the parameters are created anew.

    Returns:
      :class:`DsaKey` : a new DSA key object

    Raises:
      ValueError : when **bits** is too little, too big, or not a multiple of 64.

    .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
    Nr.   r   zInvalid DSA domain parametersz?Mismatch between size of modulus (%d) and 'bits' parameter (%d)))r   r   )r   r   )r   r   )r   r   z;Lengths of p and q (%d, %d) are not compatibleto FIPS 186-3zIncorrent DSA generatorr   )Z
exact_bitsrr   r   r   r   r   r   )r   rs   r9   r   r   r   r8   r%   r   rX   randomr   )r`   rr   rU   r   r   r   	fmt_error_r   r   r   r   r   r*   r+   r+   r,   r     s:    
Tc                 C   s   t tdtt| }t|}d}|rt|jtk}|t|jtkO }||jd |j dkO }||j	dkpr|j	|jkO }|t
|j	|j|jdkO }||jdkp|j|jkO }t|dr||jdkp|j|jkO }|t
|j	|j|j|jkO }|rtd|S )a  Construct a DSA key from a tuple of valid DSA components.

    Args:
      tup (tuple):
        A tuple of long integers, with 4 or 5 items
        in the following order:

            1. Public key (*y*).
            2. Sub-group generator (*g*).
            3. Modulus, finite field order (*p*).
            4. Sub-group order (*q*).
            5. Private key (*x*). Optional.

      consistency_check (boolean):
        If ``True``, the library will verify that the provided components
        fulfil the main DSA properties.

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

    Returns:
      :class:`DsaKey` : a DSA key object
    r   Fr.   r   r   zInvalid DSA key components)r'   zipr9   r   r   r   r   r   r   r   r8   r   rZ   r   r%   )tupZconsistency_checkr*   keyr   r+   r+   r,   r     s     
c                    sL   |rt dt j| ddd  d dkr2t d fddd	D }t|S )
Nz-DSA private key already comes with parameters   T)Znr_elementsZonly_ints_expectedr   zNo version foundc                    s   g | ]} | qS r+   r+   r0   derr+   r,   r4   '  s     z+_import_openssl_private.<locals>.<listcomp>)r      r.   r      )r%   r   decoder   )encodedrz   r}   r   r+   r   r,   _import_openssl_private!  s    r   c                 C   sj   t | \}}}|tkrtd|r.|r.tdt |j}tt |pJ|\}}}	||	||f}
t|
S )NzNo DSA subjectPublicKeyInfozToo many DSA parameters)	r   rx   r%   r   r   valuelistr   r   )r   rz   r}   ZalgoidZencoded_keyZ
emb_paramsr   r   r   r   r   r+   r+   r,   _import_subjectPublicKeyInfo+  s    r   c                 C   s   t | }t|d |S rH   )r   r   )r   rz   r}   Zsp_infor+   r+   r,   _import_x509_cert9  s    r   c           	      C   sv   |rt dt| |}|d tkr,t dt |d j}tt |d \}}}t	|||||||f}t
|S )Nz"PKCS#8 already includes parametersr   zNo PKCS#8 encoded DSA keyr.   r   )r%   r   unwraprx   r   r   r   r   r   r8   r   )	r   rz   r}   r<   r   r   r   r   r   r+   r+   r,   _import_pkcs8?  s    r   c              	   C   sJ   t tttf}|D ],}z|| ||W   S  tk
r:   Y qX qtddS )z?Import a DSA key (public or private half), encoded in DER form.DSA key format is not supportedN)r   r   r   r   r%   )Zkey_datarz   r}   Z	decodingsZdecodingr+   r+   r,   _import_key_derK  s    r   c                    s  t | } |dk	rt |}| drLtt| |\}}}|r@d}t||dS | drt| dd }g  t	|dkrt
d|dd d } |dd|   |d| d }qn d d	kr fd
ddD }t|S t	| dkrt| d dkrt| |dS tddS )a  Import a DSA key.

    Args:
      extern_key (string or byte string):
        The DSA key to import.

        The following formats are supported for a DSA **public** key:

        - X.509 certificate (binary DER or PEM)
        - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM)
        - OpenSSH (ASCII one-liner, see `RFC4253`_)

        The following formats are supported for a DSA **private** key:

        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM)
        - OpenSSL/OpenSSH custom format (binary or PEM)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (string):
        In case of an encrypted private key, this is the pass phrase
        from which the decryption key is derived.

        Encryption may be applied either at the `PKCS#8`_ or at the PEM level.

    Returns:
      :class:`DsaKey` : a DSA key object

    Raises:
      ValueError : when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
    .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
    Ns   -----rp       r.   r   rl   r   rj   c                    s   g | ]}t  | qS r+   r   rg   r{   r+   r,   r4     s     zimport_key.<locals>.<listcomp>)r   r   r.   r   0   r   )r   
startswithr   r   r	   r   rt   
a2b_base64splitro   rm   unpackrY   r   r   r%   )Z
extern_keyrz   r   markerZenc_flagr|   lengthr   r+   r   r,   r   \  s*    (

 z1.2.840.10040.4.1)NN)T)N).__all__rt   rm   r   ZCryptodome.Util.py3compatr   r   r   r	   r
   Z
Cryptodomer   ZCryptodome.IOr   r   ZCryptodome.Hashr   ZCryptodome.Util.asn1r   r   r   r   r   ZCryptodome.Math.Numbersr   ZCryptodome.Math.Primalityr   r   r   ZCryptodome.PublicKeyr   r   r   objectr   r   r   r   r   r   r   r   r   r   Z	importKeyrx   r+   r+   r+   r,   <module>   s2      5
I
8

G