o
    n~b                     @   s  d dl mZ d dlZd dlZd dlZd dlmZ d dlmZm	Z	m
Z
mZ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 d dlmZmZmZ d d	lmZmZmZmZm Z m!Z! d d
l"m#Z# d dl$m%Z% eddZ&eddZ'i Z(g da)dd Z*e*  [*g da+dd Z,e,  [,g da-dd Z.e.  [.g da/dd Z0e0  [0g da1dd Z2e2  [2G dd  d e3Z4G d!d" d"e5Z6e6e(d# j7e(d# j8d#Z9e(d# j:e9d$Z;e(<e=>t)e; [9[;b)e6e(d% j7e(d% j8d%Z?e(d% j:e?d$Z@e(<e=>t+e@ [?[@b+e6e(d& j7e(d& j8d&ZAe(d& j:eAd$ZBe(<e=>t-eB [A[Bb-e6e(d' j7e(d' j8d'ZCe(d' j:eCd$ZDe(<e=>t/eD [C[Db/e6e(d( j7e(d( j8d(ZEe(d( j:eEd$ZFe(<e=>t1eF [E[Fb1G d)d* d*e5ZGd+d, ZHd-d. ZIdHd/d0ZJd1d2 ZKdId3d4ZLd5d6 ZMd7d8 ZNd9d: ZOd;d< ZPd=d> ZQdHd?d@ZReSdAkrd dlTZTdBZUe(d& jVW ZXdCZYeTT ZZe[eYD ]Z\eXeU Z]qe^dDeTT eZ eY dE dF eTT ZZe[eYD ]Z\e]eU Z]qe^dGeTT eZ eY dE dF dS dS )J    )print_functionN)
namedtuple)bordtobytestostrbchr	is_string)bytes_to_longlong_to_bytes)Integer)DerObjectIdDerOctetStringDerSequenceDerBitString)_expand_subject_public_key_info_create_subject_public_key_info _extract_subject_public_key_info)load_pycryptodome_raw_libVoidPointerSmartPointerc_size_tc_uint8_ptrc_ulonglong)get_random_bytes)getrandbitszCryptodome.PublicKey._ec_wsav  
typedef void EcContext;
typedef void EcPoint;
int ec_ws_new_context(EcContext **pec_ctx,
                      const uint8_t *modulus,
                      const uint8_t *b,
                      const uint8_t *order,
                      size_t len,
                      uint64_t seed);
void ec_free_context(EcContext *ec_ctx);
int ec_ws_new_point(EcPoint **pecp,
                    const uint8_t *x,
                    const uint8_t *y,
                    size_t len,
                    const EcContext *ec_ctx);
void ec_free_point(EcPoint *ecp);
int ec_ws_get_xy(uint8_t *x,
                 uint8_t *y,
                 size_t len,
                 const EcPoint *ecp);
int ec_ws_double(EcPoint *p);
int ec_ws_add(EcPoint *ecpa, EcPoint *ecpb);
int ec_ws_scalar(EcPoint *ecp,
                 const uint8_t *k,
                 size_t len,
                 uint64_t seed);
int ec_ws_clone(EcPoint **pecp2, const EcPoint *ecp);
int ec_ws_copy(EcPoint *ecp1, const EcPoint *ecp2);
int ec_ws_cmp(const EcPoint *ecp1, const EcPoint *ecp2);
int ec_ws_neg(EcPoint *p);
int ec_ws_normalize(EcPoint *ecp);
int ec_ws_is_pai(EcPoint *ecp);
_Curvez7p b order Gx Gy G modulus_bits oid context desc openssh)p192
NIST P-192zP-192Z
prime192v1Z	secp192r1Znistp192c                  C      d} d}d}d}d}t | d}t |d}t |d}t }t| t|t|t|tt|tt	d}	|	r>t
d|	 t| tj}
tt| t|t|t|t|d d	d
|
dd}ttt| d S )Nl   l   9{uDjSg9g(Bl   1(i&^#a;l   +' 1t:_|v!a:@ml   H<^W]dZ{cxW\Iq    @   z#Error %d initializing P-192 context   z1.2.840.10045.3.1.1r   zecdsa-sha2-nistp192)r
   r   _ec_libec_ws_new_context
address_ofr   r   lenr   r   ImportErrorr   getec_free_contextr   r   _curvesupdatedictfromkeys
p192_names)pborderGxGyZp192_modulusZp192_bZ
p192_orderZec_p192_contextresultcontextr    r5   C/usr/local/lib/python3.10/dist-packages/Cryptodome/PublicKey/ECC.py	init_p192c   @   





r7   )p224
NIST P-224zP-224Z
prime224v1Z	secp224r1Znistp224c                  C   r   )Nl              ?l   FeY8w-X"PVd/%PP!-l   =*8%(?l   !"X!#BXtJ9!'|%VA-l   4~ 
f&Dv@h!fE0m9_qlM/   r    z#Error %d initializing P-224 context   z1.3.132.0.33r:   zecdsa-sha2-nistp224)r
   r   r"   r#   r$   r   r   r%   r   r   r&   r   r'   r(   r   r   r)   r*   r+   r,   
p224_names)r.   r/   r0   r1   r2   Zp224_modulusZp224_bZ
p224_orderZec_p224_contextr3   r4   r9   r5   r5   r6   	init_p224   r8   r>   )p256
NIST P-256zP-256Z
prime256v1Z	secp256r1Znistp256c                  C   r   )Nl   ?               @ l   K`Opq^cv
3,e<1U]>{|R*Zl   Q%x+Ohbi+}s   @ l   B11e	%:f=K`wrH7gHK8hkl   Q~o]l+fUg+<)Z?8O?q!O    r    z#Error %d initializing P-256 context   z1.2.840.10045.3.1.7r@   zecdsa-sha2-nistp256)r
   r   r"   r#   r$   r   r   r%   r   r   r&   r   r'   r(   r   r   r)   r*   r+   r,   
p256_names)r.   r/   r0   r1   r2   Zp256_modulusZp256_bZ
p256_orderZec_p256_contextr3   r4   r?   r5   r5   r6   	init_p256   r8   rD   )p384
NIST P-384zP-384Z
prime384v1Z	secp384r1Znistp384c                  C   r   )Nl          ~l   *'#.TEbc+Z'@=D 1 "(?7N2Z_+|S/1fl   s)e`gwlX_[nlv|l   
dxRjoyU8T(	:ss"nZL8k&"_Ul   _!uR/sX0
@qaNQNB&JxS8KJEY	K%l 0   r    z#Error %d initializing P-384 contexti  z1.3.132.0.34rF   zecdsa-sha2-nistp384)r
   r   r"   r#   r$   r   r   r%   r   r   r&   r   r'   r(   r   r   r)   r*   r+   r,   
p384_names)r.   r/   r0   r1   r2   Zp384_modulusZp384_bZ
p384_orderZec_p384_contextr3   r4   rE   r5   r5   r6   	init_p384   r8   rI   )p521
NIST P-521zP-521Z
prime521v1Z	secp521r1Znistp521c                  C   r   )Nl#   l#    ?VQ(zO%b95~cte1oR{V;LHw>l-rZE]"Sr&Ga9}*Fl#   	dp"z\}[z3"nZ;PK#
`7roCQl#   f=xK)H-apY$3^Q	n%k{;/K!u{4-{?$Od8V1l3s:l#   Pf?QE$XN!85aZUWL9YLhzf$Du13otc!%pMxjRr`B   r    z#Error %d initializing P-521 contexti	  z1.3.132.0.35rK   zecdsa-sha2-nistp521)r
   r   r"   r#   r$   r   r   r%   r   r   r&   r   r'   r(   r   r   r)   r*   r+   r,   
p521_names)r.   r/   r0   r1   r2   Zp521_modulusZp521_bZ
p521_orderZec_p521_contextr3   r4   rJ   r5   r5   r6   	init_p521  r8   rN   c                   @   s   e Zd ZdS )UnsupportedEccFeatureN)__name__
__module____qualname__r5   r5   r5   r6   rO   E  s    rO   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
edd Zedd Ze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 ))EccPointa=  A class to abstract a point over an Elliptic Curve.

    The class support special methods for:

    * Adding two points: ``R = S + T``
    * In-place addition: ``S += T``
    * Negating a point: ``R = -T``
    * Comparing two points: ``if S == T: ...``
    * Multiplying a point by a scalar: ``R = S*k``
    * In-place multiplication by a scalar: ``T *= k``

    :ivar x: The affine X-coordinate of the ECC point
    :vartype x: integer

    :ivar y: The affine Y-coordinate of the ECC point
    :vartype y: integer

    :ivar xy: The tuple with X- and Y- coordinates
    r?   c           	      C   s   zt | | _W n ty   tdt| w || _|  }| jj}t||}t||}t	||ks8t	||kr<tdt
 | _t| j t|t|t|| }|rd|dkr^tdtd| t| j tj| _d S )NzUnknown curve name %szIncorrect coordinate length   z)The EC point does not belong to the curvez(Error %d while instantiating an EC point)r)   _curveKeyError
ValueErrorstr_curve_namesize_in_bytesr4   r
   r%   r   _pointr"   Zec_ws_new_pointr$   r   r   r'   r   ec_free_point)	selfxycurvemodulus_bytesr4   xbybr3   r5   r5   r6   __init__^  s4   



zEccPoint.__init__c                 C   sH   t  | _t| j |j }|rtd| t| j tj| _| S )Nz"Error %d while cloning an EC point)	r   r[   r"   Zec_ws_cloner$   r'   rW   r   r\   r]   pointr3   r5   r5   r6   set~  s   
zEccPoint.setc                 C   s   dt | j |j kS Nr   )r"   Z	ec_ws_cmpr[   r'   )r]   rf   r5   r5   r6   __eq__  s   zEccPoint.__eq__c                 C   s,   |   }t|j }|rtd| |S )Nz$Error %d while inverting an EC point)copyr"   Z	ec_ws_negr[   r'   rW   )r]   npr3   r5   r5   r6   __neg__  s
   zEccPoint.__neg__c                 C   s   | j \}}t||| j}|S )zReturn a copy of this point.)xyrS   rY   )r]   r^   r_   rk   r5   r5   r6   rj     s   
zEccPoint.copyc                 C   s
   | j dkS )z*``True`` if this is the point-at-infinity.)r   r   rm   r]   r5   r5   r6   is_point_at_infinity     
zEccPoint.is_point_at_infinityc                 C   s   t dd| jS )z<Return the point-at-infinity for the curve this point is on.r   )rS   rY   ro   r5   r5   r6   point_at_infinity  s   zEccPoint.point_at_infinityc                 C   
   | j d S rh   rn   ro   r5   r5   r6   r^     rq   z
EccPoint.xc                 C   rs   )N   rn   ro   r5   r5   r6   r_     rq   z
EccPoint.yc                 C   sb   |   }t|}t|}tt|t|t|| j }|r%td| t	t
|t	t
|fS )Nz#Error %d while encoding an EC point)rZ   	bytearrayr"   Zec_ws_get_xyr   r   r[   r'   rW   r   r	   )r]   ra   rb   rc   r3   r5   r5   r6   rm     s   
zEccPoint.xyc                 C   s   |   d d S )z"Size of each coordinate, in bytes.      )size_in_bitsro   r5   r5   r6   rZ     s   zEccPoint.size_in_bytesc                 C   s   | j jS )z!Size of each coordinate, in bits.)rU   modulus_bitsro   r5   r5   r6   rx     s   zEccPoint.size_in_bitsc                 C   s$   t | j }|rtd| | S )zDouble this point (in-place operation).

        :Return:
            :class:`EccPoint` : this same object (to enable chaining)
        z#Error %d while doubling an EC point)r"   Zec_ws_doubler[   r'   rW   )r]   r3   r5   r5   r6   double  s   zEccPoint.doublec                 C   s<   t | j |j }|r|dkrtdtd| | S )zAdd a second point to this one   z#EC points are not on the same curvez#Error %d while adding two EC points)r"   Z	ec_ws_addr[   r'   rW   re   r5   r5   r6   __iadd__  s   zEccPoint.__iadd__c                 C   s   |   }||7 }|S )z8Return a new point, the addition of this one and anotherrj   )r]   rf   rk   r5   r5   r6   __add__     zEccPoint.__add__c                 C   sV   |dk rt dt|}t| j t|tt|t	t
d}|r)t d| | S )zMultiply this point by a scalarr   z?Scalar multiplication is only defined for non-negative integersr    z%Error %d during scalar multiplication)rW   r
   r"   Zec_ws_scalarr[   r'   r   r   r%   r   r   )r]   scalarsbr3   r5   r5   r6   __imul__  s   

zEccPoint.__imul__c                 C   s   |   }||9 }|S )z2Return a new point, the scalar product of this oner}   )r]   r   rk   r5   r5   r6   __mul__  r   zEccPoint.__mul__c                 C   s
   |  |S N)r   )r]   Z	left_handr5   r5   r6   __rmul__  s   
zEccPoint.__rmul__N)r?   )rP   rQ   rR   __doc__rd   rg   ri   rl   rj   rp   rr   propertyr^   r_   rm   rZ   rx   rz   r|   r~   r   r   r   r5   r5   r5   r6   rS   I  s.    
 



rS   r   )Gr9   r?   rE   rJ   c                   @   s   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	e
dd Ze
dd Zdd Zdd Zd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)S )+EccKeya  Class defining an ECC key.
    Do not instantiate directly.
    Use :func:`generate`, :func:`construct` or :func:`import_key` instead.

    :ivar curve: The name of the ECC as defined in :numref:`curve_names`.
    :vartype curve: string

    :ivar pointQ: an ECC point representating the public component
    :vartype pointQ: :class:`EccPoint`

    :ivar d: A scalar representating the private component
    :vartype d: integer
    c                 K   s   t |}|dd}|dd| _|dd| _|r"tdt| |tvr+td|t| | _| jdu r?| jdu r>tdnt	| j| _d| j  krU| jj
k sZtd	 td	| jj| _dS )
a  Create a new ECC key

        Keywords:
          curve : string
            It must be *"p256"*, *"P-256"*, *"prime256v1"* or *"secp256r1"*.
          d : integer
            Only for a private key. It must be in the range ``[1..order-1]``.
          point : EccPoint
            Mandatory for a public key. If provided for a private key,
            the implementation will NOT check whether it matches ``d``.
        r`   Ndrf   Unknown parameters: zUnsupported curve (%s)zBEither private or public ECC component must be specified, not bothrt   zInvalid ECC private component)r+   pop_dr[   	TypeErrorrX   r)   rW   rU   r   r0   descr`   )r]   kwargskwargs_
curve_namer5   r5   r6   rd     s&   



zEccKey.__init__c                 C   s    |  |   kr
dS |j| jkS )NF)has_privatepointQ)r]   otherr5   r5   r6   ri   A  s   zEccKey.__eq__c                 C   s<   |   rdt| j }nd}| jj\}}d| jj|||f S )Nz, d=%d z,EccKey(curve='%s', point_x=%d, point_y=%d%s))r   intr   r   rm   rU   r   )r]   extrar^   r_   r5   r5   r6   __repr__G  s
   zEccKey.__repr__c                 C   s
   | j duS )zJ``True`` if this key can be used for making signatures or decrypting data.N)r   ro   r5   r5   r6   r   O  s   
zEccKey.has_privatec           	      C   s   d|  k r| j jk sJ  J | j j}tjd|d}| j| }|| |}| j j| j| }||| ||   | }||fS )Nr   rt   )min_inclusivemax_exclusive)rU   r0   r   random_ranger   inverser   r^   )	r]   zkr0   ZblindZblind_dZinv_blind_krsr5   r5   r6   _signT  s    
zEccKey._signc                 C   sR   | j j}|d |}| j j|| |  }| j||d  |  }|| j|d kS )Nrt   r   )rU   r0   r   r   r   r^   )r]   r   rsr0   ZsinvZpoint1Zpoint2r5   r5   r6   _verifyb  s
   zEccKey._verifyc                 C   s   |   std| jS )NzThis is not a private ECC key)r   rW   r   ro   r5   r5   r6   r   i  s   zEccKey.dc                 C   s    | j d u r| jj| j | _ | j S r   )r[   rU   r   r   ro   r5   r5   r6   r   o  s   
zEccKey.pointQc                 C   s   t | jj| jdS )z^A matching ECC public key.

        Returns:
            a new :class:`EccKey` object
        )r`   rf   )r   rU   r   r   ro   r5   r5   r6   
public_keyu  s   zEccKey.public_keyc                 C   s^   | j  }|r| j j rd}nd}|| j j| }|S d| j j| | j j| }|S )N         )r   rZ   r_   is_oddr^   to_bytes)r]   compressra   
first_byter   r5   r5   r6   _export_SEC1~  s   

zEccKey._export_SEC1c                 C   s"   |  |}d}t||t| jjS )N1.2.840.10045.2.1)r   r   r   rU   oid)r]   r   r   unrestricted_oidr5   r5   r6   _export_subjectPublicKeyInfo  s   

z#EccKey._export_subjectPublicKeyInfoTc                 C   sx   |   sJ | j }d| jj| | jj| }dt| j|t| j	j
ddt|ddg}|s6|d= t| S )Nr   rt   r   explicit   )r   r   rZ   r^   r   r_   r   r   r   rU   r   r   r   encode)r]   include_ec_paramsra   r   seqr5   r5   r6   _export_private_der  s   


zEccKey._export_private_derc                 K   s`   ddl m} |dd d urd|vrtdd}| jdd}|j||fd	t| jji|}|S )
Nr   PKCS8
passphrase
protection5At least the 'protection' parameter should be presentr   F)r   Z
key_params)	Cryptodome.IOr   r'   rW   r   wrapr   rU   r   )r]   r   r   r   private_keyr3   r5   r5   r6   _export_pkcs8  s   
zEccKey._export_pkcs8c                 C   s"   ddl m} | |}||dS )Nr   PEMz
PUBLIC KEY)r   r   r   r   )r]   r   r   encoded_derr5   r5   r6   _export_public_pem  s   
zEccKey._export_public_pemc                 K   s*   ddl m} |  }|j|d|fi |S )Nr   r   zEC PRIVATE KEY)r   r   r   r   r]   r   r   r   r   r5   r5   r6   _export_private_pem  s   zEccKey._export_private_pemc                 C   s    ddl m} |  }||dS )Nr   r   zPRIVATE KEY)r   r   r   r   )r]   r   r   r5   r5   r6   (_export_private_clear_pkcs8_in_clear_pem  s   z/EccKey._export_private_clear_pkcs8_in_clear_pemc                 K   sD   ddl m} |s
J d|vrtd| jdd|i|}||dS )Nr   r   r   r   r   zENCRYPTED PRIVATE KEYr5   )r   r   rW   r   r   r   r5   r5   r6   ,_export_private_encrypted_pkcs8_in_clear_pem  s   z3EccKey._export_private_encrypted_pkcs8_in_clear_pemc           	      C   s   |   rtd| jj}| j }|r'd| jj  }t|| jj	
| }nd| jj	
| | jj
| }|dd }t|t||f}ddd |D }|d tt| S )	Nz"Cannot export OpenSSH private keysr   r   -    c                 S   s    g | ]}t d t|| qS )>I)structpackr%   ).0r^   r5   r5   r6   
<listcomp>  s     z*EccKey._export_openssh.<locals>.<listcomp> )r   rW   rU   opensshr   rZ   r_   r   r   r^   r   splitr   joinr   binascii
b2a_base64)	r]   r   r   ra   r   r   middlecompsZblobr5   r5   r6   _export_openssh  s$   
zEccKey._export_opensshc                 K   s>  |  }|d}|dvrtd| |dd}|  rw|dd}t|r1t|}|s1td|d	d
}|dkrU|rL|rH| j|fi |S |  S | j|fi |S |dkrq|ra|satd|rm| j	dd|i|S | 
 S td| |rtd| |dkr| |S |dkr| |S |dkr| |S | |S )a  Export this ECC key.

        Args:
          format (string):
            The format to use for encoding the key:

            - ``'DER'``. The key will be encoded in ASN.1 DER format (binary).
              For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure
              defined in `RFC5480`_ will be used.
              For a private key, the ASN.1 ``ECPrivateKey`` structure defined
              in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope,
              see the ``use_pkcs8`` flag below).
            - ``'PEM'``. The key will be encoded in a PEM_ envelope (ASCII).
            - ``'OpenSSH'``. The key will be encoded in the OpenSSH_ format
              (ASCII, public keys only).
            - ``'SEC1'``. The public key (i.e., the EC point) will be encoded
              into ``bytes`` according to Section 2.3.3 of `SEC1`_
              (which is a subset of the older X9.62 ITU standard).

          passphrase (byte string or string):
            The passphrase to use for protecting the private key.

          use_pkcs8 (boolean):
            Only relevant for private keys.

            If ``True`` (default and recommended), the `PKCS#8`_ representation
            will be used.

            If ``False``, the much weaker `PEM encryption`_ mechanism will be used.

          protection (string):
            When a private key is exported with password-protection
            and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be
            present and be a valid algorithm supported by :mod:`Cryptodome.IO.PKCS8`.
            It is recommended to use ``PBKDF2WithHMAC-SHA1AndAES128-CBC``.

          compress (boolean):
            If ``True``, the method returns a more compact representation
            of the public key, with the X-coordinate only.

            If ``False`` (default), the method returns the full public key.

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

        .. note::
            When exporting a private key with password-protection and `PKCS#8`_
            (both ``DER`` and ``PEM`` formats), any extra parameters
            to ``export_key()`` will be passed to :mod:`Cryptodome.IO.PKCS8`.

        .. _PEM:        http://www.ietf.org/rfc/rfc1421.txt
        .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        .. _OpenSSH:    http://www.openssh.com/txt/rfc5656.txt
        .. _RFC5480:    https://tools.ietf.org/html/rfc5480
        .. _RFC5915:    http://www.ietf.org/rfc/rfc5915.txt
        .. _SEC1:       https://www.secg.org/sec1-v2.pdf

        Returns:
            A multi-line string (for PEM and OpenSSH) or
            ``bytes`` (for DER and SEC1) with the encoded key.
        format)r   DERZOpenSSHSEC1zUnknown format '%s'r   Fr   NzEmpty passphrase	use_pkcs8Tr   r   z8Private keys can only be encrpyted with DER using PKCS#8z2Private keys cannot be exported in the '%s' formatzUnexpected parameters: '%s'r   r5   )rj   r   rW   r   r   r   r   r   r   r   r   r   r   r   r   )r]   r   argsZ
ext_formatr   r   r   r5   r5   r6   
export_key  sH   A




zEccKey.export_keyN)T)rP   rQ   rR   r   rd   ri   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r5   r5   r5   r6   r     s.    "

	
	r   c                  K   sP   |  d}t| }|  dt}| rtdt|  tjd|j|d}t||dS )a:  Generate a new private key on the given curve.

    Args:

      curve (string):
        Mandatory. It must be a curve name defined in :numref:`curve_names`.

      randfunc (callable):
        Optional. The RNG to read randomness from.
        If ``None``, :func:`Cryptodome.Random.get_random_bytes` is used.
    r`   randfuncr   rt   )r   r   r   )r`   r   )	r   r)   r   r   rX   r   r   r0   r   )r   r   r`   r   r   r5   r5   r6   generateg  s   
r   c                  K   s   | d }t | }| dd}| dd}d| v rtdd||fvr*t|||| d< | dd}|durHd| v rH|j| }|j||fkrHtdtd	i | S )
a(  Build a new ECC key (private or public) starting
    from some base components.

    Args:

      curve (string):
        Mandatory. It must be a curve name defined in :numref:`curve_names`.

      d (integer):
        Only for a private key. It must be in the range ``[1..order-1]``.

      point_x (integer):
        Mandatory for a public key. X coordinate (affine) of the ECC point.

      point_y (integer):
        Mandatory for a public key. Y coordinate (affine) of the ECC point.

    Returns:
      :class:`EccKey` : a new ECC key object
    r`   point_xNpoint_yrf   zUnknown keyword: pointr   z(Private and public ECC keys do not matchr5   )	r)   r   r   rS   r'   r   rm   rW   r   )r   r   r`   r   r   r   Zpub_keyr5   r5   r6   	construct  s   
r   c           	      C   sP  t  D ]\}}|r|j|kr n||kr nq|r td| td| |j }t| d }|dkrZt| dd|  krCtdt	
| d|d  }t	
| |d d }nG|d	v rt| d| krjtdt	
| dd }|d
 |d
  |j |j}|dkr| r|j| }|d
kr| r|j| }ntdt|||dS )a  Convert an encoded EC point into an EccKey object

    ec_point: byte string with the EC point (SEC1-encoded)
    curve_oid: string with the name the curve
    curve_name: string with the OID of the curve

    Either curve_id or curve_name must be specified

    Unsupported ECC curve (OID: %s)zUnsupported ECC curve (%s)r      rt   r   zIncorrect EC point lengthN)r      r   zIncorrect EC point encoding)r`   r   r   )r)   itemsr   rO   r.   rZ   r   r%   rW   r   
from_bytesr/   sqrtr   Zis_evenr   )	ec_point	curve_oidr   rY   r`   ra   Z
point_typer^   r_   r5   r5   r6   _import_public_der  s8   



r   c           	      G   sZ   t | \}}}d}d}d}||||fvrtd| |s tdt |j}t||dS )z4Convert a subjectPublicKeyInfo into an EccKey objectr   1.3.132.1.121.3.132.1.13!Unsupported ECC purpose (OID: %s)zMissing ECC parametersr   )r   rO   rW   r   decodevaluer   )	encodedr   r   r   paramsr   ecdh_oid	ecmqv_oidr   r5   r5   r6   _import_subjectPublicKeyInfo  s   
	r   c                 C   s<  t  j| dd}|d dkrtdztdd|d j}|d ur*||kr*td|}W n	 ty6   Y nw |d u r?td	t D ]\}}|j|krN nqCtd
| t	 |d j
}|j }t||krmtdt|}	t|dkrtdd|d j}
t|
|d}|jj}|jj}nd  }}t||	||dS )N)r   r   )Znr_elementsr   rt   z!Incorrect ECC private key versionr   r   zCurve mismatchzNo curve foundr   zPrivate key is too smallr   r   r   )r`   r   r   r   )r   r   rW   r   r   r)   r   r   rO   r   payloadr.   rZ   r%   r   r   r   r   r   r^   r_   r   )r   r   r   r   
parametersr   r`   Zscalar_bytesra   r   Zpublic_key_encr   r   r   r5   r5   r6   _import_private_der  s<   



r   c           
      C   s^   ddl m} || |\}}}d}d}d}||||fvr"td| t |j}	t|||	S )Nr   r   r   r   r   r   )r   r   unwraprO   r   r   r   r   )
r   r   r   Zalgo_oidr   r   r   r   r   r   r5   r5   r6   _import_pkcs8>  s   	r   c                 G   s   t | }t|S r   )r   r   )r   r   Zsp_infor5   r5   r6   _import_x509_certX  s   r   c              
   C   s  zt | |W S  ty } z|d }~w tttfy   Y nw zt| |W S  ty4 } z|d }~w tttfy?   Y nw zt| |W S  tyT } z|d }~w tttfy_   Y nw zt| |W S  tyt } z|d }~w tttfy   Y tdw )NzNot an ECC DER key)r   rO   rW   r   
IndexErrorr   r   r   )r   r   errr5   r5   r6   _import_der^  sB   r  c                 C   s   t | dd }g }t|dkr7td|d d d }||dd|   |d| d  }t|dkst D ]\}}t	|j
dd }|d |krQ nq;tdt|d |jd	S )
N    rt   r   r   r   r   r   zUnsupported ECC curver   )r   
a2b_base64r   r%   r   unpackappendr)   r   r   r   rW   r   r   )r   Z	keystringZkeypartsZlkr   r`   r   r5   r5   r6   _import_openssh_public  s   r  c                 C   s  ddl m}m}m}m} || |\}}||\}}|tvr#td| t| }	|	jd d }
||\}}t|d dkr@t	dt
|d	|
 d krNt	d
t|dd|
  }t|d|
 d  }t|||d}||\}}t|}||\}}|| t|||dS )Nrt   )import_openssh_private_generic
read_bytesread_stringcheck_paddingzUnsupported ECC curve %srv   rw   r   r   z/Only uncompressed OpenSSH EC keys are supportedr   zIncorrect public key length)r`   )r`   r   rf   )Z_opensshr  r  r	  r
  r)   rO   ry   r   rW   r%   r   r   rS   r   )datapasswordr  r  r	  r
  Zssh_nameZ	decryptednamer`   ra   r   r   r   rf   r   r   _paddedr5   r5   r6   _import_openssh_private_ecc  s(   
r  c              
   C   s`  ddl m} t| } |durt|}| dr+t| }|||\}}}t||}|S | drtt| }d}	d}
tj|	d |
 d	|tj	d
}|||\}}}|rSd}zt
||}W |S  tyi } z|d}~w tys   tdw | dr}t| S t| dkrt| d dkrt
| |S t| dkrt| d dv r|du rtdt| |dS td)a  Import an ECC key (public or private).

    Args:
      encoded (bytes or multi-line string):
        The ECC key to import.

        An ECC **public** key can be:

        - An X.509 certificate, binary (DER) or ASCII (PEM)
        - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM)
        - A SEC1_ (or X9.62) byte string. You must also provide the
          ``curve_name``.
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        An ECC **private** key can be:

        - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_)
        - In ASCII format (PEM or `OpenSSH 6.5+`_)

        Private keys can be in the clear or password-protected.

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

      passphrase (byte string):
        The passphrase to use for decrypting a private key.
        Encryption may be applied protected at the PEM level or at the PKCS#8 level.
        This parameter is ignored if the key in input is not encrypted.

      curve_name (string):
        For a SEC1 byte string only. This is the name of the ECC curve,
        as defined in :numref:`curve_names`.

    Returns:
      :class:`EccKey` : a new ECC 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
    .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    .. _`OpenSSH 6.5+`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf
    .. _SEC1: https://www.secg.org/sec1-v2.pdf
    r   r   Ns   -----BEGIN OPENSSH PRIVATE KEYs   -----z-----BEGIN EC PARAMETERS-----z-----END EC PARAMETERS-----z.*?r   )flagsz(Invalid DER encoding inside the PEM files   ecdsa-sha2-rG   s   zNo curve name was provided)r   zECC key format is not supported)r   r   r   
startswithr   r   r  resubDOTALLr  rO   rW   r  r%   r   r   )r   r   r   r   Ztext_encodedZopenssh_encodedmarkerZenc_flagr3   Zecparams_startZecparams_endZder_encodedZuefr5   r5   r6   
import_key  sL   0




r  __main__l   _,)N$chKf-5lk<Xk#E i  z	(P-256 G)i  msz(P-256 arbitrary point))NNr   )_
__future__r   r  r   r   collectionsr   ZCryptodome.Util.py3compatr   r   r   r   r   ZCryptodome.Util.numberr	   r
   ZCryptodome.Math.Numbersr   ZCryptodome.Util.asn1r   r   r   r   ZCryptodome.PublicKeyr   r   r   ZCryptodome.Util._raw_apir   r   r   r   r   r   ZCryptodome.Randomr   ZCryptodome.Random.randomr   r"   r   r)   r-   r7   r=   r>   rC   rD   rH   rI   rM   rN   rW   rO   objectrS   r1   r2   Zp192_G_replacer   r*   r+   r,   Zp224_Gr9   Zp256_Gr?   Zp384_GrE   Zp521_GrJ   r   r   r   r   r   r   r   r   r  r  r  r  rP   timer   r   rj   rf   countstartranger^   ZpointXprintr5   r5   r5   r6   <module>   s    

"&&&&& .  Y
,8
'2!
!
e 