o
    n~bW                     @   s  g d 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g 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d ZeZeZd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. ZdS )0r   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}||stdt||  || }|r1|t dkr1t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,   C/usr/local/lib/python3.10/dist-packages/Cryptodome/PublicKey/DSA.py__init__g   s   

zDsaKey.__init__c                    s      stdd|  k r jk std 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                       g | ]} j | qS r,   r)   .0compr*   r,   r-   
<listcomp>y       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,   r5   r-   _signs   s   zDsaKey._signc                    s   |\}} fdddD \}}}}d|  k r|k r*n dS d|  k r)|k s,dS  dS t ||}	|	| | }
|	| | }t||
|t||| | | }||kS )Nc                    r0   r,   r1   r2   r5   r,   r-   r6      r7   z"DsaKey._verify.<locals>.<listcomp>)r   r   r   r   r   F)r   r:   r;   )r*   r>   sigr@   rA   r   r   r   r   wu1u2vr,   r5   r-   _verify   s    zDsaKey._verifyc                 C   s
   d| j v S )z!Whether this is a DSA private keyr    r1   r5   r,   r,   r-   r8      s   
zDsaKey.has_privatec                 C      dS )NFr,   r5   r,   r,   r-   can_encrypt      zDsaKey.can_encryptc                 C   rI   )NTr,   r5   r,   r,   r-   can_sign   rK   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 Nr1   )r3   r?   r5   r,   r-   	<genexpr>   s    z$DsaKey.public_key.<locals>.<genexpr>r!   )r(   r   )r*   Zpublic_componentsr,   r5   r-   
public_key   s   zDsaKey.public_keyc                 C   sP   t |  t | krdS d}| jD ]}|o$t| j|d t|j|d k}q|S )NFT)boolr8   _keydatagetattrr)   )r*   otherresultr4   r,   r,   r-   __eq__   s   
zDsaKey.__eq__c                 C   s   |  | S rM   )rU   )r*   rS   r,   r,   r-   __ne__   s   zDsaKey.__ne__c                 C   s   ddl m} |)Nr   )PicklingError)picklerW   )r*   rW   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)   r2   r5   r,   r-   r6          z!DsaKey.domain.<locals>.<listcomp>)r   r   r   r,   r5   r,   r5   r-   domain   s   zDsaKey.domainc                 C   sz   g }| j D ] }|dkrt| 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>,)rQ   r   r   size_in_bitsappendhasattrr8   	__class____name__idjoin)r*   attrsr?   bitsr,   r,   r-   __repr__   s   



zDsaKey.__repr__c                 C   s(   zt | j| W S  ty   t|w rM   )r=   r)   KeyErrorAttributeError)r*   itemr,   r,   r-   __getattr__   s
   zDsaKey.__getattr__r   Nc                    s  |durt |}|du rtj}|dkrC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}

 r|du rWd}|ry|s]d}tj }tj|t|||
|d}|rtd}nd}d}n1|dkr|rtddjjj	jjg}t| }d}n|rtdtttj|
}d}|dkr|S |dkrt||d ||}t |S td| )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r3   r    r5   r,   r-   r6     rZ   z%DsaKey.export_key.<locals>.<listcomp>)r   r   r   r   c                 S   s    t | d d@ rtd|  S | S )Nr      )r   r   r"   r,   r,   r-   func  s   zDsaKey.export_key.<locals>.funcc                    s   g | ]} |qS r,   r,   rm   )ro   r,   r-   r6            ssh-dss    c                 S   s    g | ]}t d t|| qS )>I)structpacklen)r3   kpr,   r,   r-   r6             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_bytesrd   binascii
b2a_base64r   r   r   r   r8   r   r    encoder   wrapoidr&   r   r   r   )r*   formatZpkcs8
passphraseZ
protectionr{   Ztup1Ztup2keyparts	keystringparamsZprivate_keyZ
binary_keyZkey_typeZintsZpem_strr,   )ro   r*   r-   
export_key   sd   ;

zDsaKey.export_keyc                 C      t dNz+Use module Cryptodome.Signature.DSS insteadNotImplementedError)r*   MKr,   r,   r-   signU     zDsaKey.signc                 C   r   r   r   )r*   r   	signaturer,   r,   r-   verifyX  r   zDsaKey.verifyc                 C      t rM   r   )r*   	plaintextr   r,   r,   r-   encrypt[  rK   zDsaKey.encryptc                 C   r   rM   r   )r*   Z
ciphertextr,   r,   r-   decrypt^  rK   zDsaKey.decryptc                 C   r   rM   r   r*   r   Br,   r,   r-   blinda  rK   zDsaKey.blindc                 C   r   rM   r   r   r,   r,   r-   unblindd  rK   zDsaKey.unblindc                 C   r   rM   r   r5   r,   r,   r-   sizeg  rK   zDsaKey.size)r   NNNN)rb   
__module____qualname____doc__rQ   r.   rB   rH   r8   rJ   rL   rO   rU   rV   rY   r[   rg   rk   r   Z	exportKeyZ	publickeyr   r   r   r   r   r   r   r,   r,   r,   r-   r   N   s8    

	
~r   c                    s  dddd | }|du rtd|  tjd |  d  d }| d |  }td	}d|d > }t||tkrZ|d
tt	 |d @ }||B dB }t||tks;|
 |ksbJ dd| d > }	 fddt|d D  dd  D  t fddt|D  | d|> d @ d| >  }t|| }	|	
 | ksJ |	|d  }
|	|
d  }|
 | krt||tkrn|d 7 qk|d | }tdD ]&}d td t|  }tt|	 }t|||}|dkr nq|||fS )z+Generate a new set of DSA domain parameters         )         NzInvalid modulus length (%d)   r/      @   Tc                    s*   g | ]}t t |    qS r,   )r   newr   rl   digest)r3   j)offsetseedr,   r-   r6     s    "z$_generate_domain.<locals>.<listcomp>c                 S   s   g | ]}t |qS r,   r   
from_bytes)r3   rG   r,   r,   r-   r6     r7   c                    s    g | ]} | d | >  qS )r/   r,   )r3   i)Voutlenr,   r-   r6     rx      s   ggen)getr&   r   digest_sizer   r   r   r   r   r   r^   r
   sum	itertoolscountr   rl   r;   )Lr{   NnZb_r   Z	upper_bitUWXcr   er   r   r,   )r   r   r   r   r-   _generate_domaink  sV   

r   c                 C   sH  |du rt j}|rDtt|\}}}t|tk}|t|tkO }||d | dkO }||dkp1||kO }|t|||dkO }|rCtdn	t| |\}}}}|	 }|	 }	|| kratd|| f ||	fdvrotd||	f d|  k r||k std 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_bitsr{   r   )r   r|   r<   r   r   r   r;   r&   r   r^   randomr   )rf   r{   r[   r   r   r   	fmt_error_r   r   r   r    r   r+   r,   r,   r-   r     s@   r   Tc                 C   s   t tdtt| }t|}d}|rut|jtk}|t|jtkO }||jd |j dkO }||j	dkp9|j	|jkO }|t
|j	|j|jdkO }||jdkpS|j|jkO }t|dru||jdkpe|j|jkO }|t
|j	|j|j|jkO }|r{t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(   zipr<   r   r   r   r   r   r   r   r;   r   r`   r    r&   )tupZconsistency_checkr+   keyr   r,   r,   r-   r     s    
r   c                    sL   |rt dt j| ddd  d dkrt 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,   r2   derr,   r-   r6   '  rp   z+_import_openssl_private.<locals>.<listcomp>)r      r/   r      )r&   r   decoder   )encodedr   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 |p%|\}}}	||	||f}
t|
S )NzNo DSA subjectPublicKeyInfozToo many DSA parameters)	r   r   r&   r   r   valuelistr   r   )r   r   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 rM   )r   r   )r   r   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   unwrapr   r   r   r   r   r   r;   r   )	r   r   r   r?   r    r   r   r   r   r,   r,   r-   _import_pkcs8?  s   r   c              	   C   sB   t tttf}|D ]}z	|| ||W   S  ty   Y qw td)z?Import a DSA key (public or private half), encoded in DER form.DSA key format is not supported)r   r   r   r   r&   )Zkey_datar   r   Z	decodingsZdecodingr,   r,   r-   _import_key_derK  s   r   c                    s  t | } |durt |}| dr&tt| |\}}}|r d}t||dS | drut| dd }g  t	|dkrbt
d|dd d } |dd|   |d| d }t	|dks= d d	kru fd
ddD }t|S t	| dkrt| d dkrt| |dS td)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   -----ry       r/   r   rs   r   rq   c                    s   g | ]	}t  | qS r,   r   rm   r   r,   r-   r6     rZ   zimport_key.<locals>.<listcomp>)r   r   r/   r   0   r   )r   
startswithr   r   r	   r   r}   
a2b_base64splitrv   rt   unpackr_   r   r   r&   )Z
extern_keyr   r   markerZenc_flagr   lengthr   r,   r   r-   r   \  s,   (

r   z1.2.840.10040.4.1)NN)TrM   ).__all__r}   rt   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	importKeyr   r,   r,   r,   r-   <module>   s4      
5
I8

G