o
    e                     @   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d de/Z0G dd de1Z2e2e(d j3e(d j4dZ5e(d j6e5dZ7e(8e9:t)e7 [5[7b)e2e(d j3e(d j4dZ;e(d j6e;dZ<e(8e9:t+e< [;[<b+e2e(d  j3e(d  j4d Z=e(d  j6e=dZ>e(8e9:t-e> [=[>b-G d!d" d"e1Z?d#d$ Z@d%d& ZAd'd( ZBd)d* ZCd@d+d,ZDd-d. ZEd/d0 ZFd1d2 ZGd3d4 ZHd5d6 ZId@d7d8ZJeKd9krd dlLZLd:ZMe(d jNO ZPd;ZQeLL ZReSeQD ]ZTePeM ZUqXeVd<eLL eR eQ d= d> eLL ZReSeQD ]ZTeUeM ZUqveVd?eLL eR eQ d= d> dS dS )A    )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)p256
NIST P-256zP-256
prime256v1	secp256r1nistp256c                  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   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    @   z#Error %d initializing P-256 context   z1.2.840.10045.3.1.7r   zecdsa-sha2-nistp256)r
   r   _ec_libec_ws_new_context
address_ofr   r   lenr   r   ImportErrorr   getec_free_contextr   r   _curvesupdatedictfromkeys
p256_names)pborderGxGyp256_modulusp256_b
p256_orderec_p256_contextresultcontextr    r<   :/usr/lib/python3/dist-packages/Cryptodome/PublicKey/ECC.py	init_p256c   @   





r>   )p384
NIST P-384zP-384
prime384v1	secp384r1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.34rA   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)r1   r2   r3   r4   r5   p384_modulusp384_b
p384_orderec_p384_contextr:   r;   r@   r<   r<   r=   	init_p384   r?   rK   )p521
NIST P-521zP-521
prime521v1	secp521r1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.35rM   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)r1   r2   r3   r4   r5   p521_modulusp521_b
p521_orderec_p521_contextr:   r;   rL   r<   r<   r=   	init_p521   r?   rW   c                   @   s   e Zd ZdS )UnsupportedEccFeatureN)__name__
__module____qualname__r<   r<   r<   r=   rX      s    rX   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_bytesr;   r
   r(   r   _pointr%   ec_ws_new_pointr'   r   r   r*   r   ec_free_point)	selfxycurvemodulus_bytesr;   xbybr:   r<   r<   r=   __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   rd   r%   ec_ws_cloner'   r*   r`   r   rf   rg   pointr:   r<   r<   r=   set"  s   
zEccPoint.setc                 C   s   dt | j |j kS Nr   )r%   	ec_ws_cmprd   r*   )rg   rq   r<   r<   r=   __eq__-  s   zEccPoint.__eq__c                 C   s,   |   }t|j }|rtd| |S )Nz$Error %d while inverting an EC point)copyr%   	ec_ws_negrd   r*   r`   )rg   npr:   r<   r<   r=   __neg__0  s
   zEccPoint.__neg__c                 C   s   | j \}}t||| j}|S )zReturn a copy of this point.)xyr\   rb   )rg   rh   ri   rx   r<   r<   r=   rv   7  s   
zEccPoint.copyc                 C   s
   | j dkS )z*``True`` if this is the point-at-infinity.)r   r   rz   rg   r<   r<   r=   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   )r\   rb   r|   r<   r<   r=   point_at_infinityA  s   zEccPoint.point_at_infinityc                 C   
   | j d S rs   r{   r|   r<   r<   r=   rh   E  r~   z
EccPoint.xc                 C   r   )N   r{   r|   r<   r<   r=   ri   I  r~   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)rc   	bytearrayr%   ec_ws_get_xyr   r   rd   r*   r`   r   r	   )rg   rk   rl   rm   r:   r<   r<   r=   rz   M  s   
zEccPoint.xyc                 C   s   |   d d S )z"Size of each coordinate, in bytes.      )size_in_bitsr|   r<   r<   r=   rc   [  s   zEccPoint.size_in_bytesc                 C   s   | j jS )z!Size of each coordinate, in bits.)r^   modulus_bitsr|   r<   r<   r=   r   _  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%   ec_ws_doublerd   r*   r`   )rg   r:   r<   r<   r=   doublec  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%   	ec_ws_addrd   r*   r`   rp   r<   r<   r=   __iadd__o  s   zEccPoint.__iadd__c                 C   s   |   }||7 }|S )z8Return a new point, the addition of this one and anotherrv   )rg   rq   rx   r<   r<   r=   __add__y     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)r`   r
   r%   ec_ws_scalarrd   r*   r   r   r(   r   r   )rg   scalarsbr:   r<   r<   r=   __imul__  s   

zEccPoint.__imul__c                 C   s   |   }||9 }|S )z2Return a new point, the scalar product of this oner   )rg   r   rx   r<   r<   r=   __mul__  r   zEccPoint.__mul__c                 C   s
   |  |S N)r   )rg   	left_handr<   r<   r=   __rmul__  s   
zEccPoint.__rmul__N)r   )rY   rZ   r[   __doc__rn   rr   ru   ry   rv   r}   r   propertyrh   ri   rz   rc   r   r   r   r   r   r   r   r<   r<   r<   r=   r\      s.    
 



r\   r   )Gr@   rL   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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``.
        rj   Ndrq   Unknown parameters: zUnsupported curve (%s)zBEither private or public ECC component must be specified, not bothr   zInvalid ECC private component)r.   pop_drd   	TypeErrorra   r,   r`   r^   r   r3   descrj   )rg   kwargskwargs_
curve_namer<   r<   r=   rn     s&   



zEccKey.__init__c                 C   s    |  |   kr
dS |j| jkS )NF)has_privatepointQ)rg   otherr<   r<   r=   ru     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   rz   r^   r   )rg   extrarh   ri   r<   r<   r=   __repr__  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   r|   r<   r<   r=   r     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   r   )min_inclusivemax_exclusive)r^   r3   r   random_ranger   inverser   rh   )	rg   zkr3   blindblind_dinv_blind_krsr<   r<   r=   _sign  s    
zEccKey._signc                 C   sR   | j j}|d |}| j j|| |  }| j||d  |  }|| j|d kS )Nr   r   )r^   r3   r   r   r   rh   )rg   r   rsr3   sinvpoint1point2r<   r<   r=   _verify  s
   zEccKey._verifyc                 C   s   |   std| jS )NzThis is not a private ECC key)r   r`   r   r|   r<   r<   r=   r     s   zEccKey.dc                 C   s    | j d u r| jj| j | _ | j S r   )rd   r^   r   r   r|   r<   r<   r=   r   	  s   
zEccKey.pointQc                 C   s   t | jj| jdS )z^A matching ECC public key.

        Returns:
            a new :class:`EccKey` object
        )rj   rq   )r   r^   r   r   r|   r<   r<   r=   
public_key  s   zEccKey.public_keyc                 C   sn   | j  }|rd| j j  }t|| j j| }nd| j j| | j j| }d}t||t| j	j
S )N      1.2.840.10045.2.1)r   rc   ri   is_oddr   rh   to_bytesr   r   r^   oid)rg   compressrk   
first_byter   unrestricted_oidr<   r<   r=   _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   r   r   explicitr   )r   r   rc   rh   r   ri   r   r   r   r^   r   r   r   encode)rg   include_ec_paramsrk   r   seqr<   r<   r=   _export_private_der2  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   
key_params)	Cryptodome.IOr   r*   r`   r   wrapr   r^   r   )rg   r   r   r   private_keyr:   r<   r<   r=   _export_pkcs8M  s   
zEccKey._export_pkcs8c                 C   s"   ddl m} | |}||dS )Nr   PEMz
PUBLIC KEY)r   r   r   r   )rg   r   r   encoded_derr<   r<   r=   _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   rg   r   r   r   r   r<   r<   r=   _export_private_pema  s   zEccKey._export_private_pemc                 C   s    ddl m} |  }||dS )Nr   r   zPRIVATE KEY)r   r   r   r   )rg   r   r   r<   r<   r=   (_export_private_clear_pkcs8_in_clear_pemg  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 KEYr<   )r   r   r`   r   r   r   r<   r<   r=   ,_export_private_encrypted_pkcs8_in_clear_pemm  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(   ).0rh   r<   r<   r=   
<listcomp>  s     z*EccKey._export_openssh.<locals>.<listcomp> )r   r`   r^   opensshr   rc   ri   r   r   rh   r   splitr   joinr   binascii
b2a_base64)	rg   r   r   rk   r   r   middlecompsblobr<   r<   r=   _export_opensshv  s$   
zEccKey._export_opensshc                 K   s(  |  }|d}|dvrtd| |dd}|  ru|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 | |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).

          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``, a more compact representation of the public key
            with the X-coordinate only is used.

            If ``False`` (default), the full public key will be exported.

        .. 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

        Returns:
            A multi-line string (for PEM and OpenSSH) or bytes (for DER) with the encoded key.
        format)r   DEROpenSSHzUnknown format '%s'r   Fr   NzEmpty passphrase	use_pkcs8Tr   r   z8Private keys can only be encrpyted with DER using PKCS#8z1Private keys cannot be exported in OpenSSH formatzUnexpected parameters: '%s'r<   )rv   r   r`   r   r   r   r   r   r   r   r   r   r   r   )rg   r   args
ext_formatr   r   r   r<   r<   r=   
export_key  s@   <



zEccKey.export_keyN)T)rY   rZ   r[   r   rn   ru   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r<   r<   r<   r=   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.
    rj   randfuncr   r   )r   r   r   )rj   r   )	r   r,   r   r   ra   r   r   r3   r   )r   r   rj   r   r   r<   r<   r=   generate  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
    rj   point_xNpoint_yrq   zUnknown keyword: pointr   z(Private and public ECC keys do not matchr<   )	r,   r   r   r\   r*   r   rz   r`   r   )r   r   rj   r   r   r   pub_keyr<   r<   r=   	construct  s   
r   c                 C   s0  t  D ]\}}|j| kr nqtd|  |j }t|d }|dkrJt|dd|  kr3tdt	
|d|d  }t	
||d d }nG|dv rt|d| krZtdt	
|dd }|d	 |d	  |j |j}|dkr| r|j| }|d	kr| r|j| }ntd
t|||dS )zConvert an encoded EC point into an EccKey object

    curve_name: string with the OID of the curve
    ec_point: byte string with the EC point (not DER encoded)

    Unsupported ECC curve (OID: %s)r      r   r   zIncorrect EC point lengthN)r      r   zIncorrect EC point encoding)rj   r   r   )r,   itemsr   rX   r1   rc   r   r(   r`   r   
from_bytesr2   sqrtr   is_evenr   )	curve_oidec_pointr   rj   rk   
point_typerh   ri   r<   r<   r=   _import_public_der8  s0   




r  c           	      G   sX   t | \}}}d}d}d}||||fvrtd| |s tdt |j}t||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   rX   r`   r   decodevaluer  )	encodedr   r   r  paramsr   ecdh_oid	ecmqv_oidr  r<   r<   r=   _import_subjectPublicKeyInfog  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||
}|jj}|jj}nd  }}t||	||dS )N)r   r   )nr_elementsr   r   z!Incorrect ECC private key versionr   r   zCurve mismatchzNo curve foundr   zPrivate key is too smallr   r   )rj   r   r   r   )r   r  r`   r   r  r,   r  r   rX   r   payloadr1   rc   r(   r   r  r   r  r   rh   ri   r   )r  r   r  r   
parametersr   rj   scalar_bytesrk   r   public_key_encr   r   r   r<   r<   r=   _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   unwraprX   r   r  r  r  )
r  r   r   algo_oidr   r  r   r  r  r  r<   r<   r=   _import_pkcs8  s   	r  c                 G   s   t | }t|S r   )r   r  )r  r   sp_infor<   r<   r=   _import_x509_cert  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  rX   r`   r   
IndexErrorr  r  r  )r  r   errr<   r<   r=   _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|j|d S )	N    r   r   r   r   r   r   zUnsupported ECC curve)r   
a2b_base64r   r(   r   unpackappendr,   r  r   r   r`   r  r   )r  	keystringkeypartslkr   rj   r   r<   r<   r=   _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 )Nr   )import_openssh_private_generic
read_bytesread_stringcheck_paddingzUnsupported ECC curve %sr   r   r   r   z/Only uncompressed OpenSSH EC keys are supportedr   zIncorrect public key length)rj   )rj   r   rq   )_opensshr)  r*  r+  r,  r,   rX   r   r   r`   r(   r   r  r\   r   )datapasswordr)  r*  r+  r,  ssh_name	decryptednamerj   rk   r   r   r   rq   r   r   _paddedr<   r<   r=   _import_openssh_private_ecc  s(   
r5  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)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)
        - 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.

    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
    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-rE   zECC key format is not supported)r   r   r   
startswithr   r  r5  resubDOTALLr   rX   r`   r(  r(   r   )r  r   r   text_encodedopenssh_encodedmarkerenc_flagr:   ecparams_startecparams_endder_encodeduefr<   r<   r=   
import_key5  sD   )




rC  __main__l   _,)N$chKf-5lk<Xk#E i  z	(P-256 G)i  msz(P-256 arbitrary point)r   )W
__future__r   r8  r   r   collectionsr   Cryptodome.Util.py3compatr   r   r   r   r   Cryptodome.Util.numberr	   r
   Cryptodome.Math.Numbersr   Cryptodome.Util.asn1r   r   r   r   Cryptodome.PublicKeyr   r   r   Cryptodome.Util._raw_apir   r   r   r   r   r   Cryptodome.Randomr   Cryptodome.Random.randomr   r%   r   r,   r0   r>   rF   rK   rR   rW   r`   rX   objectr\   r4   r5   p256_G_replacer   r-   r.   r/   p384_Gr@   p521_GrL   r   r   r   r  r  r  r  r  r   r(  r5  rC  rY   timer   r   rv   rq   countstartrangerh   pointXprintr<   r<   r<   r=   <module>   s    

"&&& .  J,/
'2!
!
X 