o
    ÖèFhƒÃ  ã                   @  sø  U d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z
 d dlmZ d dlmZ d dl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mZ d d
lm Z m!Z!m"Z"m#Z#m$Z$m%Z% z
d dl&m'Z( dZ)W n e*y‰   dZ)	d‘d’dd„Z(Y nw dZ+dZ,dZ-dZ.dZ/dZ0dZ1d Z2d!Z3e 4d"¡Z5d#Z6d$Z7d%Z8d&Z9d'Z:d(Z;d)Z<e 4e7d* e8 ej=¡Z>e?e@eAd+d,ƒƒƒZBeG d-d.„ d.ƒƒZCeCejDd/ejEd)d)ddd0�eCejDd/ejFd)d)ddd0�eCejDd/ejGd)d1d)dd0�d2œZHd3eId4< e.e/e0d5œZJd“d8d9„ZKd”d<d=„ZLe7d> e8d> fd•dBdC„ZMd–dFdG„ZNd—dHdI„ZOd˜dMdN„ZPd™dQdR„ZQd™dSdT„ZRdšdVdW„ZSd™dXdY„ZTd›d[d\„ZUG d]d^„ d^ƒZVG d_d`„ d`ƒZWG dadb„ dbƒZXG dcdd„ ddƒZYG dedf„ dfƒZZe,eWƒ e-eXƒ e+eZƒ e.eYdge [¡ ƒe/eYdhe \¡ ƒe0eYdie ]¡ ƒiZ^dœdkdl„Z_ej`ejaejbejcejdf Ze	d�dždpdq„ZfdŸdudv„Zgej`ejhejiejjejkf Zlej`ejhejiejkf ZmG dwdx„ dxejnƒZoG dydz„ dzƒZpd d~d„Zq	d‘d¡d�d‚„Zrd¡dƒd„„Zsd¢d‡dˆ„Zt	d�d£dŠd‹„Zud¤dŒd�„Zvej`ejaejbejdf ZwdŽZxG d�d�„ d�ƒZydS )¥é    )ÚannotationsN)Úencodebytes)Ú	dataclass)Úutils©ÚUnsupportedAlgorithm)Úhashes)ÚdsaÚecÚed25519ÚpaddingÚrsa)ÚAEADDecryptionContextÚCipherÚ
algorithmsÚmodes)ÚEncodingÚKeySerializationEncryptionÚNoEncryptionÚPrivateFormatÚPublicFormatÚ_KeySerializationEncryption)ÚkdfTFÚpasswordÚbytesÚsaltÚdesired_key_bytesÚintÚroundsÚignore_few_roundsÚboolÚreturnc                 C  s   t dƒ‚)NzNeed bcrypt moduler   )r   r   r   r   r   © r"   úi/var/www/html/loop/nvenv/lib/python3.10/site-packages/cryptography/hazmat/primitives/serialization/ssh.pyÚ_bcrypt_kdf1   s   r$   s   ssh-ed25519s   ssh-rsas   ssh-dsss   ecdsa-sha2-nistp256s   ecdsa-sha2-nistp384s   ecdsa-sha2-nistp521s   -cert-v01@openssh.coms   rsa-sha2-256s   rsa-sha2-512s   \A(\S+)[ \t]+(\S+)s   openssh-key-v1 s#   -----BEGIN OPENSSH PRIVATE KEY-----s!   -----END OPENSSH PRIVATE KEY-----s   bcrypts   noneó
   aes256-ctré   s   (.*?)é   é   c                   @  sF   e Zd ZU ded< ded< ded< ded< ded< d	ed
< ded< dS )Ú
_SSHCipherztype[algorithms.AES]Úalgr   Úkey_lenz3type[modes.CTR] | type[modes.CBC] | type[modes.GCM]ÚmodeÚ	block_lenÚiv_lenú
int | NoneÚtag_lenr    Úis_aeadN)Ú__name__Ú
__module__Ú__qualname__Ú__annotations__r"   r"   r"   r#   r)   X   s   
 r)   é    )r*   r+   r,   r-   r.   r0   r1   é   )r%   s
   aes256-cbcs   aes256-gcm@openssh.comzdict[bytes, _SSHCipher]Ú_SSH_CIPHERS)Ú	secp256r1Ú	secp384r1Ú	secp521r1Úkeyú&SSHPrivateKeyTypes | SSHPublicKeyTypesc                 C  sŠ   t | tjƒrt|  ¡ ƒ}|S t | tjƒrt| ƒ}|S t | tjtjfƒr't	}|S t | t
jt
jfƒr4t}|S t | tjtjfƒrAt}|S tdƒ‚)NúUnsupported key type)Ú
isinstancer
   ÚEllipticCurvePrivateKeyÚ_ecdsa_key_typeÚ
public_keyÚEllipticCurvePublicKeyr   ÚRSAPrivateKeyÚRSAPublicKeyÚ_SSH_RSAr	   ÚDSAPrivateKeyÚDSAPublicKeyÚ_SSH_DSAr   ÚEd25519PrivateKeyÚEd25519PublicKeyÚ_SSH_ED25519Ú
ValueError)r<   Úkey_typer"   r"   r#   Ú_get_ssh_key_typeŠ   s$   óõ
÷ùÿþrO   rB   úec.EllipticCurvePublicKeyc                 C  s*   | j }|jtvrtd|j›�ƒ‚t|j S )z3Return SSH key_type and curve_name for private key.z'Unsupported curve for ssh private key: )ÚcurveÚnameÚ_ECDSA_KEY_TYPErM   )rB   rQ   r"   r"   r#   rA   �   s   

ÿ
rA   ó   
ÚdataÚprefixÚsuffixc                 C  s   d  |t| ƒ|g¡S )Nó    )ÚjoinÚ_base64_encode)rU   rV   rW   r"   r"   r#   Ú_ssh_pem_encode§   s   r[   r-   ÚNonec                 C  s    | r
t | ƒ| dkrtdƒ‚dS )zRequire data to be full blocksr   zCorrupt data: missing paddingN)ÚlenrM   )rU   r-   r"   r"   r#   Ú_check_block_size¯   s   ÿr^   c                 C  s   | rt dƒ‚dS )z!All data should have been parsed.zCorrupt data: unparsed dataN)rM   ©rU   r"   r"   r#   Ú_check_emptyµ   s   ÿr`   Ú
ciphernameúbytes | Noneú)Cipher[modes.CBC | modes.CTR | modes.GCM]c                 C  sV   |st dƒ‚t|  }t|||j|j |dƒ}t| |d|j… ¡| ||jd… ¡ƒS )z$Generate key + iv and return cipher.zKey is password-protected.TN)rM   r8   r$   r+   r.   r   r*   r,   )ra   r   r   r   ÚciphÚseedr"   r"   r#   Ú_init_cipher»   s   ÿþrf   Ú
memoryviewútuple[int, memoryview]c                 C  ó6   t | ƒdk r
tdƒ‚tj| dd… dd�| dd… fS )ÚUint32é   úInvalid dataNÚbig©Ú	byteorder©r]   rM   r   Ú
from_bytesr_   r"   r"   r#   Ú_get_u32Ï   ó   "rr   c                 C  ri   )ÚUint64é   rl   Nrm   rn   rp   r_   r"   r"   r#   Ú_get_u64Ö   rs   rv   útuple[memoryview, memoryview]c                 C  s8   t | ƒ\}} |t| ƒkrtdƒ‚| d|… | |d… fS )zBytes with u32 length prefixrl   N)rr   r]   rM   )rU   Únr"   r"   r#   Ú_get_sshstrÝ   s   ry   c                 C  s4   t | ƒ\}} |r|d dkrtdƒ‚t |d¡| fS )zBig integer.r   é   rl   rm   )ry   rM   r   rq   )rU   Úvalr"   r"   r#   Ú
_get_mpintå   s   r|   r{   c                 C  s4   | dk rt dƒ‚| sdS |  ¡ d d }t | |¡S )z!Storage format for signed bigint.r   znegative mpint not allowedrX   ru   )rM   Ú
bit_lengthr   Úint_to_bytes)r{   Únbytesr"   r"   r#   Ú	_to_mpintí   s   r€   c                   @  sx   e Zd ZU dZded< d#d$d	d
„Zd%dd„Zd&dd„Zd&dd„Zd'dd„Z	d&dd„Z
d(dd„Zd)d*dd „Zd+d!d"„ZdS ),Ú	_FragListz,Build recursive structure without data copy.úlist[bytes]ÚflistNÚinitúlist[bytes] | Noner!   r\   c                 C  s   g | _ |r| j  |¡ d S d S ©N)rƒ   Úextend)Úselfr„   r"   r"   r#   Ú__init__ü   s   ÿz_FragList.__init__r{   r   c                 C  s   | j  |¡ dS )zAdd plain bytesN)rƒ   Úappend©rˆ   r{   r"   r"   r#   Úput_raw  ó   z_FragList.put_rawr   c                 C  ó   | j  |jddd�¡ dS )zBig-endian uint32rk   rm   ©Úlengthro   N©rƒ   rŠ   Úto_bytesr‹   r"   r"   r#   Úput_u32  ó   z_FragList.put_u32c                 C  rŽ   )zBig-endian uint64ru   rm   r�   Nr‘   r‹   r"   r"   r#   Úput_u64	  r”   z_FragList.put_u64úbytes | _FragListc                 C  sN   t |tttfƒr|  t|ƒ¡ | j |¡ dS |  | ¡ ¡ | j 	|j¡ dS )zBytes prefixed with u32 lengthN)
r?   r   rg   Ú	bytearrayr“   r]   rƒ   rŠ   Úsizer‡   r‹   r"   r"   r#   Ú
put_sshstr  s
   z_FragList.put_sshstrc                 C  s   |   t|ƒ¡ dS )z*Big-endian bigint prefixed with u32 lengthN)r™   r€   r‹   r"   r"   r#   Ú	put_mpint  s   z_FragList.put_mpintc                 C  s   t tt| jƒƒS )zCurrent number of bytes)ÚsumÚmapr]   rƒ   ©rˆ   r"   r"   r#   r˜     r�   z_FragList.sizer   Údstbufrg   Úposc                 C  s2   | j D ]}t|ƒ}||| }}||||…< q|S )zWrite into bytearray)rƒ   r]   )rˆ   rž   rŸ   ÚfragÚflenÚstartr"   r"   r#   Úrender  s
   
z_FragList.renderc                 C  s"   t t|  ¡ ƒƒ}|  |¡ | ¡ S )zReturn as bytes)rg   r—   r˜   r£   Útobytes)rˆ   Úbufr"   r"   r#   r¤   &  s   
z_FragList.tobytesr†   )r„   r…   r!   r\   )r{   r   r!   r\   )r{   r   r!   r\   )r{   r–   r!   r\   ©r!   r   )r   )rž   rg   rŸ   r   r!   r   ©r!   r   )r2   r3   r4   Ú__doc__r5   r‰   rŒ   r“   r•   r™   rš   r˜   r£   r¤   r"   r"   r"   r#   r�   ÷   s   
 




	
r�   c                   @  sB   e Zd ZdZddd„Zddd	„Zddd„Zddd„Zddd„ZdS )Ú_SSHFormatRSAzhFormat for RSA keys.

    Public:
        mpint e, n
    Private:
        mpint n, e, d, iqmp, p, q
    rU   rg   c                 C  s$   t |ƒ\}}t |ƒ\}}||f|fS )zRSA public fields©r|   )rˆ   rU   Úerx   r"   r"   r#   Ú
get_public6  s   z_SSHFormatRSA.get_publicr!   ú#tuple[rsa.RSAPublicKey, memoryview]c                 C  s.   |   |¡\\}}}t ||¡}| ¡ }||fS )zMake RSA public key from data.)r¬   r   ÚRSAPublicNumbersrB   )rˆ   rU   r«   rx   Úpublic_numbersrB   r"   r"   r#   Úload_public<  s   z_SSHFormatRSA.load_publicú$tuple[rsa.RSAPrivateKey, memoryview]c              	   C  s¦   t |ƒ\}}t |ƒ\}}t |ƒ\}}t |ƒ\}}t |ƒ\}}t |ƒ\}}||f|kr.tdƒ‚t ||¡}	t ||¡}
t ||¡}t ||||	|
||¡}| ¡ }||fS )zMake RSA private key from data.z Corrupt data: rsa field mismatch)r|   rM   r   Úrsa_crt_dmp1Úrsa_crt_dmq1r®   ÚRSAPrivateNumbersÚprivate_key)rˆ   rU   Ú	pubfieldsrx   r«   ÚdÚiqmpÚpÚqÚdmp1Údmq1r¯   Úprivate_numbersrµ   r"   r"   r#   Úload_privateE  s    ÿz_SSHFormatRSA.load_privaterB   úrsa.RSAPublicKeyÚf_pubr�   r\   c                 C  s$   |  ¡ }| |j¡ | |j¡ dS )zWrite RSA public keyN)r¯   rš   r«   rx   )rˆ   rB   rÀ   Úpubnr"   r"   r#   Úencode_public[  s   z_SSHFormatRSA.encode_publicrµ   úrsa.RSAPrivateKeyÚf_privc                 C  sZ   |  ¡ }|j}| |j¡ | |j¡ | |j¡ | |j¡ | |j¡ | |j¡ dS )zWrite RSA private keyN)	r½   r¯   rš   rx   r«   r·   r¸   r¹   rº   )rˆ   rµ   rÄ   r½   r¯   r"   r"   r#   Úencode_privatec  s   z_SSHFormatRSA.encode_privateN)rU   rg   )rU   rg   r!   r­   )rU   rg   r!   r±   )rB   r¿   rÀ   r�   r!   r\   )rµ   rÃ   rÄ   r�   r!   r\   ©	r2   r3   r4   r¨   r¬   r°   r¾   rÂ   rÅ   r"   r"   r"   r#   r©   -  s    


	
r©   c                   @  sL   e Zd ZdZddd„Zd d	d
„Zd!dd„Zd"dd„Zd#dd„Zd$dd„Z	dS )%Ú_SSHFormatDSAzhFormat for DSA keys.

    Public:
        mpint p, q, g, y
    Private:
        mpint p, q, g, y, x
    rU   rg   r!   útuple[tuple, memoryview]c                 C  s@   t |ƒ\}}t |ƒ\}}t |ƒ\}}t |ƒ\}}||||f|fS )zDSA public fieldsrª   )rˆ   rU   r¹   rº   ÚgÚyr"   r"   r#   r¬   |  s
   z_SSHFormatDSA.get_publicú#tuple[dsa.DSAPublicKey, memoryview]c           	      C  sJ   |   |¡\\}}}}}t |||¡}t ||¡}|  |¡ | ¡ }||fS )zMake DSA public key from data.)r¬   r	   ÚDSAParameterNumbersÚDSAPublicNumbersÚ	_validaterB   )	rˆ   rU   r¹   rº   rÉ   rÊ   Úparameter_numbersr¯   rB   r"   r"   r#   r°   „  s   
z_SSHFormatDSA.load_publicú$tuple[dsa.DSAPrivateKey, memoryview]c                 C  sz   |   |¡\\}}}}}t|ƒ\}}||||f|krtdƒ‚t |||¡}t ||¡}	|  |	¡ t ||	¡}
|
 ¡ }||fS )zMake DSA private key from data.z Corrupt data: dsa field mismatch)	r¬   r|   rM   r	   rÌ   rÍ   rÎ   ÚDSAPrivateNumbersrµ   )rˆ   rU   r¶   r¹   rº   rÉ   rÊ   ÚxrÏ   r¯   r½   rµ   r"   r"   r#   r¾   �  s   
z_SSHFormatDSA.load_privaterB   údsa.DSAPublicKeyrÀ   r�   r\   c                 C  sL   |  ¡ }|j}|  |¡ | |j¡ | |j¡ | |j¡ | |j¡ dS )zWrite DSA public keyN)r¯   rÏ   rÎ   rš   r¹   rº   rÉ   rÊ   )rˆ   rB   rÀ   r¯   rÏ   r"   r"   r#   rÂ   Ÿ  s   
z_SSHFormatDSA.encode_publicrµ   údsa.DSAPrivateKeyrÄ   c                 C  s$   |   | ¡ |¡ | | ¡ j¡ dS )zWrite DSA private keyN)rÂ   rB   rš   r½   rÒ   )rˆ   rµ   rÄ   r"   r"   r#   rÅ   ¬  s   z_SSHFormatDSA.encode_privater¯   údsa.DSAPublicNumbersc                 C  s    |j }|j ¡ dkrtdƒ‚d S )Ni   z#SSH supports only 1024 bit DSA keys)rÏ   r¹   r}   rM   )rˆ   r¯   rÏ   r"   r"   r#   rÎ   ³  s   ÿz_SSHFormatDSA._validateN©rU   rg   r!   rÈ   )rU   rg   r!   rË   )rU   rg   r!   rÐ   )rB   rÓ   rÀ   r�   r!   r\   )rµ   rÔ   rÄ   r�   r!   r\   )r¯   rÕ   r!   r\   )
r2   r3   r4   r¨   r¬   r°   r¾   rÂ   rÅ   rÎ   r"   r"   r"   r#   rÇ   s  s    




rÇ   c                   @  sL   e Zd ZdZd!dd„Zd"dd„Zd#dd„Zd$dd„Zd%dd„Zd&dd„Z	d S )'Ú_SSHFormatECDSAz–Format for ECDSA keys.

    Public:
        str curve
        bytes point
    Private:
        str curve
        bytes point
        mpint secret
    Ússh_curve_namer   rQ   úec.EllipticCurvec                 C  s   || _ || _d S r†   )rØ   rQ   )rˆ   rØ   rQ   r"   r"   r#   r‰   Å  s   
z_SSHFormatECDSA.__init__rU   rg   r!   rÈ   c                 C  sJ   t |ƒ\}}t |ƒ\}}|| jkrtdƒ‚|d dkrtdƒ‚||f|fS )zECDSA public fieldszCurve name mismatchr   rk   zNeed uncompressed point)ry   rØ   rM   ÚNotImplementedError)rˆ   rU   rQ   Úpointr"   r"   r#   r¬   É  s   
z_SSHFormatECDSA.get_publicú,tuple[ec.EllipticCurvePublicKey, memoryview]c                 C  s.   |   |¡\\}}}tj | j| ¡ ¡}||fS )z Make ECDSA public key from data.)r¬   r
   rC   Úfrom_encoded_pointrQ   r¤   )rˆ   rU   Ú_rÛ   rB   r"   r"   r#   r°   Ó  s
   
ÿz_SSHFormatECDSA.load_publicú-tuple[ec.EllipticCurvePrivateKey, memoryview]c                 C  sH   |   |¡\\}}}t|ƒ\}}||f|krtdƒ‚t || j¡}||fS )z!Make ECDSA private key from data.z"Corrupt data: ecdsa field mismatch)r¬   r|   rM   r
   Úderive_private_keyrQ   )rˆ   rU   r¶   Ú
curve_namerÛ   Úsecretrµ   r"   r"   r#   r¾   Ý  s   z_SSHFormatECDSA.load_privaterB   rP   rÀ   r�   r\   c                 C  s*   |  tjtj¡}| | j¡ | |¡ dS )zWrite ECDSA public keyN)Úpublic_bytesr   ÚX962r   ÚUncompressedPointr™   rØ   )rˆ   rB   rÀ   rÛ   r"   r"   r#   rÂ   é  s
   ÿz_SSHFormatECDSA.encode_publicrµ   úec.EllipticCurvePrivateKeyrÄ   c                 C  s,   |  ¡ }| ¡ }|  ||¡ | |j¡ dS )zWrite ECDSA private keyN)rB   r½   rÂ   rš   Úprivate_value)rˆ   rµ   rÄ   rB   r½   r"   r"   r#   rÅ   ó  s   z_SSHFormatECDSA.encode_privateN)rØ   r   rQ   rÙ   rÖ   )rU   rg   r!   rÜ   )rU   rg   r!   rß   )rB   rP   rÀ   r�   r!   r\   )rµ   ræ   rÄ   r�   r!   r\   )
r2   r3   r4   r¨   r‰   r¬   r°   r¾   rÂ   rÅ   r"   r"   r"   r#   r×   ¹  s    







r×   c                   @  sB   e Zd ZdZddd„Zdd	d
„Zddd„Zddd„Zddd„ZdS ) Ú_SSHFormatEd25519z~Format for Ed25519 keys.

    Public:
        bytes point
    Private:
        bytes point
        bytes secret_and_point
    rU   rg   r!   rÈ   c                 C  s   t |ƒ\}}|f|fS )zEd25519 public fields)ry   )rˆ   rU   rÛ   r"   r"   r#   r¬     s   
z_SSHFormatEd25519.get_publicú+tuple[ed25519.Ed25519PublicKey, memoryview]c                 C  s(   |   |¡\\}}tj | ¡ ¡}||fS )z"Make Ed25519 public key from data.)r¬   r   rK   Úfrom_public_bytesr¤   )rˆ   rU   rÛ   rB   r"   r"   r#   r°     s
   ÿz_SSHFormatEd25519.load_publicú,tuple[ed25519.Ed25519PrivateKey, memoryview]c                 C  sb   |   |¡\\}}t|ƒ\}}|dd… }|dd… }||ks#|f|kr'tdƒ‚tj |¡}||fS )z#Make Ed25519 private key from data.Nr6   z$Corrupt data: ed25519 field mismatch)r¬   ry   rM   r   rJ   Úfrom_private_bytes)rˆ   rU   r¶   rÛ   Úkeypairrâ   Úpoint2rµ   r"   r"   r#   r¾     s   z_SSHFormatEd25519.load_privaterB   úed25519.Ed25519PublicKeyrÀ   r�   r\   c                 C  s   |  tjtj¡}| |¡ dS )zWrite Ed25519 public keyN)rã   r   ÚRawr   r™   )rˆ   rB   rÀ   Úraw_public_keyr"   r"   r#   rÂ   %  s   ÿz_SSHFormatEd25519.encode_publicrµ   úed25519.Ed25519PrivateKeyrÄ   c                 C  sR   |  ¡ }| tjtjtƒ ¡}| tjtj¡}t||gƒ}|  	||¡ | 
|¡ dS )zWrite Ed25519 private keyN)rB   Úprivate_bytesr   rð   r   r   rã   r   r�   rÂ   r™   )rˆ   rµ   rÄ   rB   Úraw_private_keyrñ   Ú	f_keypairr"   r"   r#   rÅ   .  s   ÿÿz _SSHFormatEd25519.encode_privateNrÖ   )rU   rg   r!   ré   )rU   rg   r!   rë   )rB   rï   rÀ   r�   r!   r\   )rµ   rò   rÄ   r�   r!   r\   rÆ   r"   r"   r"   r#   rè   þ  s    
	



	rè   s   nistp256s   nistp384s   nistp521rN   c                 C  s4   t | tƒst| ƒ ¡ } | tv rt|  S td| ›�ƒ‚)z"Return valid format or throw errorzUnsupported key type: )r?   r   rg   r¤   Ú_KEY_FORMATSr   )rN   r"   r"   r#   Ú_lookup_kformatI  s
   
r÷   Úbackendú
typing.AnyÚSSHPrivateKeyTypesc                 C  sä  t  d| ¡ |durt  d|¡ t | ¡}|stdƒ‚| d¡}| d¡}t 	t
| ƒ||… ¡} |  t¡s9tdƒ‚t
| ƒttƒd… } t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}	} |	dkrctdƒ‚t| ƒ\}
} t|
ƒ\}}
t|ƒ}| |
¡\}}
t|
ƒ ||fttfk�r| ¡ }|tvr–td|›�ƒ‚|tkr¡td|›�ƒ‚t| j}t| j}t| ƒ\}} t| jrÅt| ƒ}t|ƒ|krÄtd	ƒ‚nt| ƒ t||ƒ t|ƒ\}}t|ƒ\}}t|ƒ t||| ¡ |ƒ}| ¡ }t
| |¡ƒ}t| j�rt |t!ƒsÿJ ‚t| "|¡ƒ nt| #¡ ƒ nt| ƒ\}} t| ƒ d
}t||ƒ t|ƒ\}}t|ƒ\}}||k�r4tdƒ‚t|ƒ\}}||k�rCtdƒ‚| $||¡\}}t|ƒ\}}|t%dt|ƒ… k�r`tdƒ‚t |t&j'ƒ�rpt(j)dt j*dd� |S )z.Load private key from OpenSSH custom encoding.rU   Nr   zNot OpenSSH private key formatr'   zOnly one key supportedzUnsupported cipher: zUnsupported KDF: z+Corrupt data: invalid tag length for cipherru   zCorrupt data: broken checksumzCorrupt data: key type mismatchzCorrupt data: invalid paddingúDSSH DSA keys are deprecated and will be removed in a future release.é   ©Ú
stacklevel)+r   Ú_check_byteslikeÚ_check_bytesÚ_PEM_RCÚsearchrM   r¢   ÚendÚbinasciiÚ
a2b_base64rg   Ú
startswithÚ	_SK_MAGICr]   ry   rr   r÷   r¬   r`   Ú_NONEr¤   r8   r   Ú_BCRYPTr-   r0   r1   r   r^   rf   Ú	decryptorÚupdater?   r   Úfinalize_with_tagÚfinalizer¾   Ú_PADDINGr	   rG   ÚwarningsÚwarnÚDeprecatedIn40)rU   r   rø   ÚmÚp1Úp2ra   ÚkdfnameÚ
kdfoptionsÚnkeysÚpubdataÚpub_key_typeÚkformatr¶   Úciphername_bytesÚblklenr0   ÚedataÚtagr   Úkbufr   rd   ÚdecÚck1Úck2rN   rµ   rÞ   r"   r"   r#   Úload_ssh_private_keyZ  s’   



ÿ


ÿ



ür#  rµ   Úencryption_algorithmr   c                 C  sä  t  d|¡ t| tjƒrtjdt jdd� t| ƒ}t	|ƒ}t
ƒ }|rQt}t| j}t}t}	t|tƒr:|jdur:|j}	t d¡}
| |
¡ | |	¡ t|||
|	ƒ}nt }}d}d}d}t d¡}d	}t
ƒ }| |¡ | |  ¡ |¡ t
||gƒ}| |¡ | | |¡ | |¡ | td|| ¡ |  … ¡ t
ƒ }| t¡ | |¡ | |¡ | |¡ | |¡ | |¡ | |¡ | ¡ }| ¡ }tt || ƒƒ}| !|¡ || }|durê| "¡  #|||… ||d… ¡ t$|d|… ƒS )
z3Serialize private key with OpenSSH custom encoding.r   úISSH DSA key support is deprecated and will be removed in a future releaserk   rý   Nr&   ru   r'   rX   )%r   r   r?   r	   rG   r  r  r  rO   r÷   r�   Ú_DEFAULT_CIPHERr8   r-   r	  Ú_DEFAULT_ROUNDSr   Ú_kdf_roundsÚosÚurandomr™   r“   rf   r  rÂ   rB   rÅ   rŒ   r  r˜   r  rg   r—   r£   Ú	encryptorÚupdate_intor[   )rµ   r   r$  rN   r  Úf_kdfoptionsra   r  r  r   r   rd   r  ÚcheckvalÚcommentÚf_public_keyÚ	f_secretsÚf_mainÚslenÚmlenr¥   Úofsr"   r"   r#   Ú_serialize_ssh_private_keyÂ  sj   ü
ÿ















 r6  c                   @  s   e Zd ZdZdZdS )ÚSSHCertificateTyper'   rü   N)r2   r3   r4   ÚUSERÚHOSTr"   r"   r"   r#   r7    s    r7  c                   @  s¼   e Zd Zd9dd„Zed:dd„ƒZd;dd„Zed<d d!„ƒZed=d#d$„ƒZed:d%d&„ƒZ	ed>d'd(„ƒZ
ed<d)d*„ƒZed<d+d,„ƒZed?d-d.„ƒZed?d/d0„ƒZd;d1d2„Zd:d3d4„Zd@d6d7„Zd8S )AÚSSHCertificateÚ_noncerg   Ú_public_keyÚSSHPublicKeyTypesÚ_serialr   Ú_cctypeÚ_key_idÚ_valid_principalsr‚   Ú_valid_afterÚ_valid_beforeÚ_critical_optionsúdict[bytes, bytes]Ú_extensionsÚ	_sig_typeÚ_sig_keyÚ_inner_sig_typeÚ
_signatureÚ_tbs_cert_bodyÚ_cert_key_typer   Ú
_cert_bodyc                 C  sŠ   || _ || _|| _zt|ƒ| _W n ty   tdƒ‚w || _|| _|| _|| _	|	| _
|
| _|| _|| _|| _|| _|| _|| _|| _d S )NzInvalid certificate type)r;  r<  r>  r7  Ú_typerM   r@  rA  rB  rC  rD  rF  rG  rH  rI  rJ  rL  rM  rK  )rˆ   r;  r<  r>  r?  r@  rA  rB  rC  rD  rF  rG  rH  rI  rJ  rK  rL  rM  r"   r"   r#   r‰   #  s*   ÿ
zSSHCertificate.__init__r!   c                 C  ó
   t | jƒS r†   )r   r;  r�   r"   r"   r#   ÚnonceL  ó   
zSSHCertificate.nonceÚSSHCertPublicKeyTypesc                 C  s   t  t| j¡S r†   )ÚtypingÚcastrR  r<  r�   r"   r"   r#   rB   P  s   zSSHCertificate.public_keyc                 C  ó   | j S r†   )r>  r�   r"   r"   r#   ÚserialU  ó   zSSHCertificate.serialr7  c                 C  rU  r†   )rN  r�   r"   r"   r#   ÚtypeY  rW  zSSHCertificate.typec                 C  rO  r†   )r   r@  r�   r"   r"   r#   Úkey_id]  rQ  zSSHCertificate.key_idc                 C  rU  r†   )rA  r�   r"   r"   r#   Úvalid_principalsa  rW  zSSHCertificate.valid_principalsc                 C  rU  r†   )rC  r�   r"   r"   r#   Úvalid_beforee  rW  zSSHCertificate.valid_beforec                 C  rU  r†   )rB  r�   r"   r"   r#   Úvalid_afteri  rW  zSSHCertificate.valid_afterc                 C  rU  r†   )rD  r�   r"   r"   r#   Úcritical_optionsm  rW  zSSHCertificate.critical_optionsc                 C  rU  r†   )rF  r�   r"   r"   r#   Ú
extensionsq  rW  zSSHCertificate.extensionsc                 C  s&   t | jƒ}| | j¡\}}t|ƒ |S r†   )r÷   rG  r°   rH  r`   )rˆ   Ú	sigformatÚsignature_keyÚsigkey_restr"   r"   r#   r`  u  s   
zSSHCertificate.signature_keyc                 C  s"   t | jƒd tjt | jƒdd� S )Nó    F)Únewline)r   rL  r  Ú
b2a_base64rM  r�   r"   r"   r#   rã   {  s   ÿþÿzSSHCertificate.public_bytesr\   c                 C  s  |   ¡ }t|tjƒr| t| jƒt| jƒ¡ d S t|tj	ƒrIt
| jƒ\}}t
|ƒ\}}t|ƒ t ||¡}t|jƒ}| |t| jƒt |¡¡ d S t|tjƒsQJ ‚| jtkr[t ¡ }n| jtkret ¡ }n| jtkslJ ‚t ¡ }| t| jƒt| jƒt ¡ |¡ d S r†   )r`  r?   r   rK   Úverifyr   rJ  rK  r
   rC   r|   r`   Ú
asym_utilsÚencode_dss_signatureÚ_get_ec_hash_algrQ   ÚECDSAr   rE   rI  rF   r   ÚSHA1Ú_SSH_RSA_SHA256ÚSHA256Ú_SSH_RSA_SHA512ÚSHA512r   ÚPKCS1v15)rˆ   r`  ÚrrU   ÚsÚcomputed_sigÚhash_algr"   r"   r#   Úverify_cert_signature‚  s6   ÿ
ÿ



üz$SSHCertificate.verify_cert_signatureN)"r;  rg   r<  r=  r>  r   r?  r   r@  rg   rA  r‚   rB  r   rC  r   rD  rE  rF  rE  rG  rg   rH  rg   rI  rg   rJ  rg   rK  rg   rL  r   rM  rg   r§   )r!   rR  r¦   )r!   r7  )r!   r‚   )r!   rE  )r!   r\   )r2   r3   r4   r‰   ÚpropertyrP  rB   rV  rX  rY  rZ  r[  r\  r]  r^  r`  rã   rt  r"   r"   r"   r#   r:  "  s0    
)


r:  rQ   rÙ   úhashes.HashAlgorithmc                 C  s@   t | tjƒr
t ¡ S t | tjƒrt ¡ S t | tjƒsJ ‚t ¡ S r†   )	r?   r
   Ú	SECP256R1r   rl  Ú	SECP384R1ÚSHA384Ú	SECP521R1rn  )rQ   r"   r"   r#   rh  £  s   rh  ú"SSHCertificate | SSHPublicKeyTypesc           "      C  sp  t  d| ¡ t | ¡}|stdƒ‚| d¡ }}| d¡}d}| t¡r/d}|d ttƒ … }|t	kr9|s9t
dƒ‚t|ƒ}z	tt |¡ƒ}W n ttjfyT   tdƒ‚w |rY|}	t|ƒ\}
}|
|krgtd	ƒ‚|rot|ƒ\}}| |¡\}}|�r2t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\}}g }|r¤t|ƒ\}}| t|ƒ¡ |s•t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ}t|ƒ\}}t|ƒ}t|ƒ\}}t|ƒ\}}t|ƒ\}}|t	krà|sàt
d
ƒ‚|	d t|ƒ … }t|ƒ\}}t|ƒ t|ƒ\}} |tk�r|tttfv�s|tk�r||k�rtdƒ‚t| ƒ\}!} t| ƒ t||||||||||||||!|||	ƒS t|ƒ |S )NrU   zInvalid line formatr'   rü   FTz-DSA keys aren't supported in SSH certificateszInvalid formatzInvalid key formatz3DSA signatures aren't supported in SSH certificatesz!Signature key type does not match)r   rÿ   Ú_SSH_PUBKEY_RCÚmatchrM   ÚgroupÚendswithÚ_CERT_SUFFIXr]   rI   r   r÷   rg   r  r  Ú	TypeErrorÚErrorry   r°   rv   rr   rŠ   r   Ú_parse_exts_optsr`   rF   rk  rm  r:  )"rU   Ú_legacy_dsa_allowedr  rN   Úorig_key_typeÚkey_bodyÚ	with_certr  ÚrestÚ	cert_bodyÚinner_key_typerP  rB   rV  ÚcctyperY  Ú
principalsrZ  Ú	principalr\  r[  Úcrit_optionsr]  Úextsr^  rÞ   Úsig_key_rawÚsig_typeÚsig_keyÚtbs_cert_bodyÚsignature_rawÚinner_sig_typeÚsig_restÚ	signaturer"   r"   r#   Ú_load_ssh_public_identity­  s¨   


ÿÿþÿ
ÿïr˜  c                 C  s   t | ƒS r†   )r˜  r_   r"   r"   r#   Úload_ssh_public_identity  s   r™  Ú	exts_optsrE  c                 C  s˜   i }d }| rJt | ƒ\}} t|ƒ}||v rtdƒ‚|d ur$||k r$tdƒ‚t | ƒ\}} t|ƒdkr@t |ƒ\}}t|ƒdkr@tdƒ‚t|ƒ||< |}| s|S )NzDuplicate namezFields not lexically sortedr   z!Unexpected extra data after value)ry   r   rM   r]   )rš  ÚresultÚ	last_namerR   ÚbnameÚvalueÚextrar"   r"   r#   rƒ    s$   órƒ  r=  c                 C  sF   t | dd�}t|tƒr| ¡ }n|}t|tjƒr!tjdtj	dd� |S )NT)r„  rû   rü   rý   )
r˜  r?   r:  rB   r	   rH   r  r  r   r  )rU   rø   Úcert_or_keyrB   r"   r"   r#   Úload_ssh_public_key&  s   

ür¡  c                 C  sl   t | tjƒrtjdtjdd� t| ƒ}t|ƒ}t	ƒ }| 
|¡ | | |¡ t | ¡ ¡ ¡ }d |d|g¡S )z&One-line public key format for OpenSSHr%  rk   rý   rX   rb  )r?   r	   rH   r  r  r   r  rO   r÷   r�   r™   rÂ   r  rd  r¤   ÚstriprY   )rB   rN   r  rÀ   Úpubr"   r"   r#   Úserialize_ssh_public_key:  s   ü
r¤  é   c                
   @  s˜   e Zd Zddddg dddg g f
d>dd„Zd?dd„Zd@dd„ZdAd!d"„ZdBd%d&„ZdCd(d)„Zd*d+„ Z	dDd.d/„Z
dEd1d2„ZdFd5d6„ZdFd7d8„ZdGd<d=„ZdS )HÚSSHCertificateBuilderNFr<  úSSHCertPublicKeyTypes | Noner>  r/   rN  úSSHCertificateType | Noner@  rb   rA  r‚   Ú_valid_for_all_principalsr    rC  rB  rD  úlist[tuple[bytes, bytes]]rF  c                 C  s@   || _ || _|| _|| _|| _|| _|| _|| _|	| _|
| _	d S r†   ©
r<  r>  rN  r@  rA  r©  rC  rB  rD  rF  )rˆ   r<  r>  rN  r@  rA  r©  rC  rB  rD  rF  r"   r"   r#   r‰   [  s   
zSSHCertificateBuilder.__init__rB   rR  r!   c                 C  s^   t |tjtjtjfƒstdƒ‚| jd urt	dƒ‚t
|| j| j| j| j| j| j| j| j| jd�
S )Nr>   zpublic_key already setr«  )r?   r
   rC   r   rE   r   rK   r�  r<  rM   r¦  r>  rN  r@  rA  r©  rC  rB  rD  rF  )rˆ   rB   r"   r"   r#   rB   s  s,   ýþ
öz SSHCertificateBuilder.public_keyrV  r   c                 C  sv   t |tƒs	tdƒ‚d|  krdk stdƒ‚ tdƒ‚| jd ur$tdƒ‚t| j|| j| j| j	| j
| j| j| j| jd�
S )Nzserial must be an integerr   ì            z"serial must be between 0 and 2**64zserial already setr«  )r?   r   r�  rM   r>  r¦  r<  rN  r@  rA  r©  rC  rB  rD  rF  )rˆ   rV  r"   r"   r#   rV  �  s(   
ÿ
özSSHCertificateBuilder.serialrX  r7  c                 C  sR   t |tƒs	tdƒ‚| jd urtdƒ‚t| j| j|| j| j	| j
| j| j| j| jd�
S )Nz"type must be an SSHCertificateTypeztype already setr«  )r?   r7  r�  rN  rM   r¦  r<  r>  r@  rA  r©  rC  rB  rD  rF  )rˆ   rX  r"   r"   r#   rX  ¤  s    

özSSHCertificateBuilder.typerY  r   c                 C  sR   t |tƒs	tdƒ‚| jd urtdƒ‚t| j| j| j|| j	| j
| j| j| j| jd�
S )Nzkey_id must be byteszkey_id already setr«  )r?   r   r�  r@  rM   r¦  r<  r>  rN  rA  r©  rC  rB  rD  rF  )rˆ   rY  r"   r"   r#   rY  ·  s    

özSSHCertificateBuilder.key_idrZ  c                 C  s|   | j rtdƒ‚tdd„ |D ƒƒr|stdƒ‚| jrtdƒ‚t|ƒtkr'tdƒ‚t| j| j	| j
| j|| j | j| j| j| jd�
S )NzDPrincipals can't be set because the cert is valid for all principalsc                 s  s   � | ]}t |tƒV  qd S r†   )r?   r   )Ú.0rÒ   r"   r"   r#   Ú	<genexpr>Ó  s   € z9SSHCertificateBuilder.valid_principals.<locals>.<genexpr>z5principals must be a list of bytes and can't be emptyzvalid_principals already setz:Reached or exceeded the maximum number of valid_principalsr«  )r©  rM   Úallr�  rA  r]   Ú_SSHKEY_CERT_MAX_PRINCIPALSr¦  r<  r>  rN  r@  rC  rB  rD  rF  )rˆ   rZ  r"   r"   r#   rZ  Ê  s:   ÿÿþÿÿöz&SSHCertificateBuilder.valid_principalsc                 C  sJ   | j rtdƒ‚| jrtdƒ‚t| j| j| j| j| j d| j| j	| j
| jd�
S )Nz@valid_principals already set, can't set valid_for_all_principalsz$valid_for_all_principals already setTr«  )rA  rM   r©  r¦  r<  r>  rN  r@  rC  rB  rD  rF  r�   r"   r"   r#   Úvalid_for_all_principalsî  s$   ÿöz.SSHCertificateBuilder.valid_for_all_principalsr[  úint | floatc                 C  sv   t |ttfƒstdƒ‚t|ƒ}|dk s|dkrtdƒ‚| jd ur$tdƒ‚t| j| j| j	| j
| j| j|| j| j| jd�
S )Nz$valid_before must be an int or floatr   r¬  zvalid_before must [0, 2**64)zvalid_before already setr«  )r?   r   Úfloatr�  rM   rC  r¦  r<  r>  rN  r@  rA  r©  rB  rD  rF  )rˆ   r[  r"   r"   r#   r[    s&   
öz"SSHCertificateBuilder.valid_beforer\  c                 C  sv   t |ttfƒstdƒ‚t|ƒ}|dk s|dkrtdƒ‚| jd ur$tdƒ‚t| j| j| j	| j
| j| j| j|| j| jd�
S )Nz#valid_after must be an int or floatr   r¬  zvalid_after must [0, 2**64)zvalid_after already setr«  )r?   r   r³  r�  rM   rB  r¦  r<  r>  rN  r@  rA  r©  rC  rD  rF  )rˆ   r\  r"   r"   r#   r\    s&   
öz!SSHCertificateBuilder.valid_afterrR   rž  c                 C  st   t |tƒr
t |tƒstdƒ‚|dd„ | jD ƒv rtdƒ‚t| j| j| j| j	| j
| j| j| jg | j¢||f‘| jd�
S )Núname and value must be bytesc                 S  ó   g | ]\}}|‘qS r"   r"   ©r­  rR   rÞ   r"   r"   r#   Ú
<listcomp>6  ó    z=SSHCertificateBuilder.add_critical_option.<locals>.<listcomp>zDuplicate critical option namer«  )r?   r   r�  rD  rM   r¦  r<  r>  rN  r@  rA  r©  rC  rB  rF  ©rˆ   rR   rž  r"   r"   r#   Úadd_critical_option0  s    öz)SSHCertificateBuilder.add_critical_optionc                 C  st   t |tƒr
t |tƒstdƒ‚|dd„ | jD ƒv rtdƒ‚t| j| j| j| j	| j
| j| j| j| jg | j¢||f‘d�
S )Nr´  c                 S  rµ  r"   r"   r¶  r"   r"   r#   r·  L  r¸  z7SSHCertificateBuilder.add_extension.<locals>.<listcomp>zDuplicate extension namer«  )r?   r   r�  rF  rM   r¦  r<  r>  rN  r@  rA  r©  rC  rB  rD  r¹  r"   r"   r#   Úadd_extensionF  s    öz#SSHCertificateBuilder.add_extensionrµ   ÚSSHCertPrivateKeyTypesr:  c              	   C  sè  t |tjtjtjfƒstdƒ‚| jd u rt	dƒ‚| j
d u rdn| j
}| jd u r+t	dƒ‚| jd u r2dn| j}| js?| js?t	dƒ‚| jd u rHt	dƒ‚| jd u rQt	dƒ‚| j| jkr[t	d	ƒ‚| jjd
d„ d� | jjdd„ d� t| jƒ}|t }t d¡}t|ƒ}tƒ }| |¡ | |¡ | | j|¡ | |¡ | | jj¡ | |¡ tƒ }	| jD ]}
|	 |
¡ qª| |	 ¡ ¡ | | j¡ | | j¡ tƒ }| jD ]$\}}| |¡ t |ƒdkrêtƒ }| |¡ | | ¡ ¡ qË| |¡ qË| | ¡ ¡ tƒ }| jD ]%\}}| |¡ t |ƒdk�rtƒ }| |¡ | | ¡ ¡ qý| |¡ qý| | ¡ ¡ | d¡ t|ƒ}t|ƒ}tƒ }| |¡ | | !¡ |¡ | | ¡ ¡ t |tjƒ�rq| "| ¡ ¡}tƒ }| |¡ | |¡ | | ¡ ¡ nlt |tjƒ�r³t#|j$ƒ}| "| ¡ t %|¡¡}t& '|¡\}}tƒ }| |¡ tƒ }| (|¡ | (|¡ | | ¡ ¡ | | ¡ ¡ n*t |tjƒ�s¼J ‚tƒ }| t)¡ | "| ¡ t* +¡ t, -¡ ¡}| |¡ | | ¡ ¡ t. /| ¡ ¡ 0¡ }t1 2t3t4d 5|d|g¡ƒ¡S )NzUnsupported private key typezpublic_key must be setr   ztype must be setrX   zAvalid_principals must be set if valid_for_all_principals is Falsezvalid_before must be setzvalid_after must be setz-valid_after must be earlier than valid_beforec                 S  ó   | d S ©Nr   r"   ©rÒ   r"   r"   r#   Ú<lambda>‡  ó    z,SSHCertificateBuilder.sign.<locals>.<lambda>)r<   c                 S  r½  r¾  r"   r¿  r"   r"   r#   rÀ  ˆ  rÁ  r6   rb  )6r?   r
   r@   r   rD   r   rJ   r�  r<  rM   r>  rN  r@  rA  r©  rC  rB  rD  ÚsortrF  rO   r€  r)  r*  r÷   r�   r™   rÂ   r•   r“   rž  r¤   r]   rB   Úsignrh  rQ   ri  rf  Údecode_dss_signaturerš   rm  r   ro  r   rn  r  rd  r¢  rS  rT  r:  r™  rY   )rˆ   rµ   rV  rY  rN   Úcert_prefixrP  r  ÚfÚfprincipalsr¹   ÚfcritrR   rž  ÚfoptvalÚfextÚfextvalÚca_typeÚcaformatÚcafr—  Úfsigrs  rp  rq  ÚfsigblobÚ	cert_datar"   r"   r#   rÃ  \  sÄ   ýþ

ÿ





















ÿ
þzSSHCertificateBuilder.sign)r<  r§  r>  r/   rN  r¨  r@  rb   rA  r‚   r©  r    rC  r/   rB  r/   rD  rª  rF  rª  )rB   rR  r!   r¦  )rV  r   r!   r¦  )rX  r7  r!   r¦  )rY  r   r!   r¦  )rZ  r‚   r!   r¦  )r[  r²  r!   r¦  )r\  r²  r!   r¦  )rR   r   rž  r   r!   r¦  )rµ   r¼  r!   r:  )r2   r3   r4   r‰   rB   rV  rX  rY  rZ  r±  r[  r\  rº  r»  rÃ  r"   r"   r"   r#   r¦  Z  s.    õ




$



r¦  )F)r   r   r   r   r   r   r   r   r   r    r!   r   )r<   r=   r!   r   )rB   rP   r!   r   )rU   r   rV   r   rW   r   r!   r   )rU   r   r-   r   r!   r\   )rU   r   r!   r\   )
ra   r   r   rb   r   r   r   r   r!   rc   )rU   rg   r!   rh   )rU   rg   r!   rw   )r{   r   r!   r   )rN   r   r†   )rU   r   r   rb   rø   rù   r!   rú   )rµ   rú   r   r   r$  r   r!   r   )rQ   rÙ   r!   rv  )rU   r   r!   r{  )rš  rg   r!   rE  )rU   r   rø   rù   r!   r=  )rB   r=  r!   r   )zÚ
__future__r   r  Úenumr)  ÚrerS  r  Úbase64r   rZ   Údataclassesr   Úcryptographyr   Úcryptography.exceptionsr   Úcryptography.hazmat.primitivesr   Ú)cryptography.hazmat.primitives.asymmetricr	   r
   r   r   r   rf  Ú&cryptography.hazmat.primitives.ciphersr   r   r   r   Ú,cryptography.hazmat.primitives.serializationr   r   r   r   r   r   Úbcryptr   r$   Ú_bcrypt_supportedÚImportErrorrL   rF   rI   Ú_ECDSA_NISTP256Ú_ECDSA_NISTP384Ú_ECDSA_NISTP521r€  rk  rm  Úcompiler|  r  Ú	_SK_STARTÚ_SK_ENDr	  r  r&  r'  ÚDOTALLr  rg   r—   Úranger  r)   ÚAESÚCTRÚCBCÚGCMr8   r5   rS   rO   rA   r[   r^   r`   rf   rr   rv   ry   r|   r€   r�   r©   rÇ   r×   rè   rw  rx  rz  rö   r÷   ÚUnionr@   rD   rG   rJ   rú   r#  r6  rC   rE   rH   rK   r=  rR  ÚEnumr7  r:  rh  r˜  r™  rƒ  r¡  r¤  r¼  r°  r¦  r"   r"   r"   r#   Ú<module>   s"   	ûý
ù	ù	ùí ý

ý








6FFEBú

	ýÿý
hMýÿþÿ 
þ
_
ÿ
þÿ	