o
    �)%aW  ã                   @   s.  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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 z
d d	lmZ d
ZW n e yv   dZ	d[de!de!de"de"de#de!fdd„ZY nw dZ$dZ%dZ&dZ'dZ(dZ)dZ*e +d¡Z,dZ-dZ.dZ/dZ0d Z1d!Z2d"Z3d#Z4e +e.d$ e/ ej5¡Z6e7e8e9d%d&ƒƒƒZ:ej;d'ej<d"fej;d'ej=d"fd(œZ>e'e(e)d)œZ?e @d*¡ZAe @d+¡ZBd,d-„ ZCe.d. e/d. fd/d0„ZDd1d2„ ZEd3d4„ ZFd5d6„ ZGd7d8„ ZHd9d:„ ZId;d<„ ZJd=d>„ ZKd?d@„ ZLG dAdB„ dBeMƒZNG dCdD„ dDeMƒZOG dEdF„ dFeMƒZPG dGdH„ dHeMƒZQG dIdJ„ dJeMƒZRe%eOƒ e&ePƒ e$eRƒ e'eQdKe S¡ ƒe(eQdLe T¡ ƒe)eQdMe U¡ ƒiZVdNdO„ ZWejXejYejZej[ej\f Z]	d\dPe!dej^e! de]fdQdR„Z_	d\dSe]dej^e! fdTdU„Z`ejXejaejbejcejdf Zed\dPe!deefdVdW„ZfdXeede!fdYdZ„ZgdS )]é    N)Úencodebytes)Úutils©ÚUnsupportedAlgorithm)Ú_get_backend)ÚdsaÚecÚed25519Úrsa)ÚCipherÚ
algorithmsÚmodes)ÚEncodingÚNoEncryptionÚPrivateFormatÚPublicFormat)ÚkdfTFÚpasswordÚsaltÚdesired_key_bytesÚroundsÚignore_few_roundsÚreturnc                 C   s   t dƒ‚)NzNeed bcrypt moduler   )r   r   r   r   r   © r   úR/usr/lib/python3/dist-packages/cryptography/hazmat/primitives/serialization/ssh.pyÚ_bcrypt_kdf    s   r   s   ssh-ed25519s   ssh-rsas   ssh-dsss   ecdsa-sha2-nistp256s   ecdsa-sha2-nistp384s   ecdsa-sha2-nistp521s   -cert-v01@openssh.coms   \A(\S+)[ \t]+(\S+)s   openssh-key-v1 s#   -----BEGIN OPENSSH PRIVATE KEY-----s!   -----END OPENSSH PRIVATE KEY-----s   bcrypts   noneó
   aes256-ctré   éH   s   (.*?)é   é   é    )r   s
   aes256-cbc)Ú	secp256r1Ú	secp384r1Ú	secp521r1s   >Is   >Qc                 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: %r)ÚcurveÚnameÚ_ECDSA_KEY_TYPEÚ
ValueError)Ú
public_keyr%   r   r   r   Ú_ecdsa_key_typeS   s   
ÿ
r*   ó   
c                 C   s   d  |t| ƒ|g¡S )Nó    )ÚjoinÚ_base64_encode)ÚdataÚprefixÚsuffixr   r   r   Ú_ssh_pem_encode]   s   r2   c                 C   s    | r
t | ƒ| dkrtdƒ‚dS )zRequire data to be full blocksr   zCorrupt data: missing paddingN)Úlenr(   )r/   Ú	block_lenr   r   r   Ú_check_block_sizea   s   ÿr5   c                 C   s   | rt dƒ‚dS )z!All data should have been parsed.zCorrupt data: unparsed dataN)r(   ©r/   r   r   r   Ú_check_emptyg   s   ÿr7   c           
      C   sT   |st dƒ‚t|  \}}}}t|||| |dƒ}	t||	d|… ƒ||	|d… ƒ|ƒS )z$Generate key + iv and return cipher.zKey is password-protected.TN)r(   Ú_SSH_CIPHERSr   r   )
Ú
ciphernamer   r   r   ÚbackendÚalgoÚkey_lenÚmodeÚiv_lenÚseedr   r   r   Ú_init_cipherm   s
   $r@   c                 C   ó6   t | ƒdk r
tdƒ‚t | dd… ¡d | dd… fS )ÚUint32é   úInvalid dataNr   )r3   r(   Ú_U32Úunpackr6   r   r   r   Ú_get_u32w   ó   "rG   c                 C   rA   )ÚUint64é   rD   Nr   )r3   r(   Ú_U64rF   r6   r   r   r   Ú_get_u64~   rH   rL   c                 C   s8   t | ƒ\}} |t| ƒkrtdƒ‚| d|… | |d… fS )zBytes with u32 length prefixrD   N)rG   r3   r(   )r/   Únr   r   r   Ú_get_sshstr…   s   rN   c                 C   s4   t | ƒ\}} |r|d dkrtdƒ‚t |d¡| fS )zBig integer.r   é   rD   Úbig)rN   r(   ÚintÚ
from_bytes)r/   Úvalr   r   r   Ú
_get_mpint�   s   rT   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 allowedr,   rJ   )r(   Ú
bit_lengthr   Úint_to_bytes)rS   Únbytesr   r   r   Ú	_to_mpint•   s   rX   c                   @   sT   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d„Z
dd„ ZdS )Ú	_FragListz,Build recursive structure without data copy.Nc                 C   s   g | _ |r| j  |¡ d S d S ©N)ÚflistÚextend)ÚselfÚinitr   r   r   Ú__init__¢   s   ÿz_FragList.__init__c                 C   s   | j  |¡ dS )zAdd plain bytesN)r[   Úappend©r]   rS   r   r   r   Úput_raw§   ó   z_FragList.put_rawc                 C   s   | j  t |¡¡ dS )zBig-endian uint32N)r[   r`   rE   Úpackra   r   r   r   Úput_u32«   s   z_FragList.put_u32c                 C   sN   t |tttfƒr|  t|ƒ¡ | j |¡ dS |  | ¡ ¡ | j 	|j¡ dS )zBytes prefixed with u32 lengthN)
Ú
isinstanceÚbytesÚ
memoryviewÚ	bytearrayre   r3   r[   r`   Úsizer\   ra   r   r   r   Ú
put_sshstr¯   s
   z_FragList.put_sshstrc                 C   s   |   t|ƒ¡ dS )z*Big-endian bigint prefixed with u32 lengthN)rk   rX   ra   r   r   r   Ú	put_mpint¸   s   z_FragList.put_mpintc                 C   s   t tt| jƒƒS )zCurrent number of bytes)ÚsumÚmapr3   r[   )r]   r   r   r   rj   ¼   rc   z_FragList.sizer   c                 C   s2   | j D ]}t|ƒ}||| }}||||…< q|S )zWrite into bytearray)r[   r3   )r]   ÚdstbufÚposÚfragÚflenÚstartr   r   r   ÚrenderÀ   s
   
z_FragList.renderc                 C   s"   t t|  ¡ ƒƒ}|  |¡ | ¡ S )zReturn as bytes)rh   ri   rj   rt   Útobytes)r]   Úbufr   r   r   ru   È   s   
z_FragList.tobytesrZ   )r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r_   rb   re   rk   rl   rj   rt   ru   r   r   r   r   rY   Ÿ   s    
	
rY   c                   @   ó8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )Ú_SSHFormatRSAzhFormat for RSA keys.

    Public:
        mpint e, n
    Private:
        mpint n, e, d, iqmp, p, q
    c                 C   s$   t |ƒ\}}t |ƒ\}}||f|fS )zRSA public fields©rT   )r]   r/   ÚerM   r   r   r   Ú
get_publicØ   s   z_SSHFormatRSA.get_publicc                 C   s0   |   |¡\\}}}t ||¡}| |¡}||fS )zMake RSA public key from data.)r   r
   ÚRSAPublicNumbersr)   )r]   Úkey_typer/   r:   r~   rM   Úpublic_numbersr)   r   r   r   Úload_publicÞ   s   
z_SSHFormatRSA.load_publicc              	   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)rT   r(   r
   Úrsa_crt_dmp1Úrsa_crt_dmq1r€   ÚRSAPrivateNumbersÚprivate_key)r]   r/   Ú	pubfieldsr:   rM   r~   ÚdÚiqmpÚpÚqÚdmp1Údmq1r‚   Úprivate_numbersr‡   r   r   r   Úload_privateå   s    ÿ
z_SSHFormatRSA.load_privatec                 C   s$   |  ¡ }| |j¡ | |j¡ dS )zWrite RSA public keyN)r‚   rl   r~   rM   )r]   r)   Úf_pubÚpubnr   r   r   Úencode_publicù   s   z_SSHFormatRSA.encode_publicc                 C   sZ   |  ¡ }|j}| |j¡ | |j¡ | |j¡ | |j¡ | |j¡ | |j¡ dS )zWrite RSA private keyN)	r�   r‚   rl   rM   r~   r‰   rŠ   r‹   rŒ   )r]   r‡   Úf_privr�   r‚   r   r   r   Úencode_privateÿ   s   z_SSHFormatRSA.encode_privateN©	rw   rx   ry   rz   r   rƒ   r�   r“   r•   r   r   r   r   r|   Ï   s    r|   c                   @   ó@   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )Ú_SSHFormatDSAzhFormat for DSA keys.

    Public:
        mpint p, q, g, y
    Private:
        mpint p, q, g, y, x
    c                 C   s@   t |ƒ\}}t |ƒ\}}t |ƒ\}}t |ƒ\}}||||f|fS )zDSA public fieldsr}   )r]   r/   r‹   rŒ   ÚgÚyr   r   r   r     s
   z_SSHFormatDSA.get_publicc                 C   sL   |   |¡\\}}}}}t |||¡}t ||¡}	|  |	¡ |	 |¡}
|
|fS )zMake DSA public key from data.)r   r   ÚDSAParameterNumbersÚDSAPublicNumbersÚ	_validater)   )r]   r�   r/   r:   r‹   rŒ   r™   rš   Úparameter_numbersr‚   r)   r   r   r   rƒ     s   

z_SSHFormatDSA.load_publicc                 C   s|   |   |¡\\}}}}}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   rT   r(   r   r›   rœ   r�   ÚDSAPrivateNumbersr‡   )r]   r/   rˆ   r:   r‹   rŒ   r™   rš   Úxrž   r‚   r�   r‡   r   r   r   r�   '  s   

z_SSHFormatDSA.load_privatec                 C   sL   |  ¡ }|j}|  |¡ | |j¡ | |j¡ | |j¡ | |j¡ dS )zWrite DSA public keyN)r‚   rž   r�   rl   r‹   rŒ   r™   rš   )r]   r)   r‘   r‚   rž   r   r   r   r“   5  s   
z_SSHFormatDSA.encode_publicc                 C   s$   |   | ¡ |¡ | | ¡ j¡ dS )zWrite DSA private keyN)r“   r)   rl   r�   r    )r]   r‡   r”   r   r   r   r•   @  s   z_SSHFormatDSA.encode_privatec                 C   s    |j }|j ¡ dkrtdƒ‚d S )Ni   z#SSH supports only 1024 bit DSA keys)rž   r‹   rU   r(   )r]   r‚   rž   r   r   r   r�   E  s   ÿz_SSHFormatDSA._validateN)
rw   rx   ry   rz   r   rƒ   r�   r“   r•   r�   r   r   r   r   r˜     s    	r˜   c                   @   r—   )Ú_SSHFormatECDSAz–Format for ECDSA keys.

    Public:
        str curve
        bytes point
    Private:
        str curve
        bytes point
        mpint secret
    c                 C   s   || _ || _d S rZ   )Ússh_curve_namer%   )r]   r¢   r%   r   r   r   r_   W  s   
z_SSHFormatECDSA.__init__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   rC   zNeed uncompressed point)rN   r¢   r(   ÚNotImplementedError)r]   r/   r%   Úpointr   r   r   r   [  s   
z_SSHFormatECDSA.get_publicc                 C   s.   |   |¡\\}}}tj | j| ¡ ¡}||fS )z Make ECDSA public key from data.)r   r   ÚEllipticCurvePublicKeyÚfrom_encoded_pointr%   ru   )r]   r�   r/   r:   Ú
curve_namer¤   r)   r   r   r   rƒ   e  s
   
ÿz_SSHFormatECDSA.load_publicc                 C   sJ   |   |¡\\}}}t|ƒ\}}||f|krtdƒ‚t || j|¡}||fS )z!Make ECDSA private key from data.z"Corrupt data: ecdsa field mismatch)r   rT   r(   r   Úderive_private_keyr%   )r]   r/   rˆ   r:   r§   r¤   Úsecretr‡   r   r   r   r�   m  s   z_SSHFormatECDSA.load_privatec                 C   s*   |  tjtj¡}| | j¡ | |¡ dS )zWrite ECDSA public keyN)Úpublic_bytesr   ÚX962r   ÚUncompressedPointrk   r¢   )r]   r)   r‘   r¤   r   r   r   r“   w  s
   ÿz_SSHFormatECDSA.encode_publicc                 C   s,   |  ¡ }| ¡ }|  ||¡ | |j¡ dS )zWrite ECDSA private keyN)r)   r�   r“   rl   Úprivate_value)r]   r‡   r”   r)   r�   r   r   r   r•     s   z_SSHFormatECDSA.encode_privateN)
rw   rx   ry   rz   r_   r   rƒ   r�   r“   r•   r   r   r   r   r¡   K  s    

r¡   c                   @   r{   )Ú_SSHFormatEd25519z~Format for Ed25519 keys.

    Public:
        bytes point
    Private:
        bytes point
        bytes secret_and_point
    c                 C   s   t |ƒ\}}|f|fS )zEd25519 public fields)rN   )r]   r/   r¤   r   r   r   r   ’  s   
z_SSHFormatEd25519.get_publicc                 C   s(   |   |¡\\}}tj | ¡ ¡}||fS )z"Make Ed25519 public key from data.)r   r	   ÚEd25519PublicKeyÚfrom_public_bytesru   )r]   r�   r/   r:   r¤   r)   r   r   r   rƒ   —  s
   ÿz_SSHFormatEd25519.load_publicc           	      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.Nr!   z$Corrupt data: ed25519 field mismatch)r   rN   r(   r	   ÚEd25519PrivateKeyÚfrom_private_bytes)	r]   r/   rˆ   r:   r¤   Úkeypairr©   Úpoint2r‡   r   r   r   r�   Ÿ  s   z_SSHFormatEd25519.load_privatec                 C   s   |  tjtj¡}| |¡ dS )zWrite Ed25519 public keyN)rª   r   ÚRawr   rk   )r]   r)   r‘   Úraw_public_keyr   r   r   r“   «  s   ÿz_SSHFormatEd25519.encode_publicc                 C   sR   |  ¡ }| tjtjtƒ ¡}| tjtj¡}t||gƒ}|  	||¡ | 
|¡ dS )zWrite Ed25519 private keyN)r)   Úprivate_bytesr   rµ   r   r   rª   r   rY   r“   rk   )r]   r‡   r”   r)   Úraw_private_keyr¶   Ú	f_keypairr   r   r   r•   ²  s   ÿÿz _SSHFormatEd25519.encode_privateNr–   r   r   r   r   r®   ˆ  s    	r®   s   nistp256s   nistp384s   nistp521c                 C   s2   t | tƒst| ƒ ¡ } | tv rt|  S td|  ƒ‚)z"Return valid format or throw errorzUnsupported key type: %r)rf   rg   rh   ru   Ú_KEY_FORMATSr   )r�   r   r   r   Ú_lookup_kformatË  s
   
r»   r/   c                 C   sJ  t  d| ¡ t|ƒ}|durt  d|¡ t | ¡}|stdƒ‚| d¡}| d¡}t	 
t| ƒ||… ¡} |  t¡s=tdƒ‚t| ƒttƒd… } t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}	} |	dkrgtdƒ‚t| ƒ\}
} t|
ƒ\}}
t|ƒ}| |
¡\}}
t|
ƒ t| ƒ\}} t| ƒ ||fttfkrÛ| ¡ }|tvr¢td| ƒ‚|tkr¬td| ƒ‚t| d	 }t||ƒ t|ƒ\}}t|ƒ\}}t|ƒ t||| ¡ ||ƒ}t| ¡  |¡ƒ}nd
}t||ƒ t|ƒ\}}t|ƒ\}}||krötdƒ‚t|ƒ\}}||k�rtdƒ‚| |||¡\}}t|ƒ\}}|tdt|ƒ… k�r#tdƒ‚|S )z.Load private key from OpenSSH custom encoding.r/   Nr   zNot OpenSSH private key formatr   zOnly one key supportedzUnsupported cipher: %rzUnsupported KDF: %ré   rJ   zCorrupt data: broken checksumzCorrupt data: key type mismatchzCorrupt data: invalid padding)r   Ú_check_bytesliker   Ú_check_bytesÚ_PEM_RCÚsearchr(   rs   ÚendÚbinasciiÚ
a2b_base64rh   Ú
startswithÚ	_SK_MAGICr3   rN   rG   r»   r   r7   Ú_NONEru   r8   r   Ú_BCRYPTr5   r@   Ú	decryptorÚupdater�   Ú_PADDING)r/   r   r:   ÚmÚp1Úp2r9   ÚkdfnameÚ
kdfoptionsÚnkeysÚpubdataÚpub_key_typeÚkformatrˆ   ÚedataÚblklenr   Úkbufr   ÚciphÚck1Úck2r�   r‡   Úcommentr   r   r   Úload_ssh_private_keyÜ  sn   




ÿ

rÛ   r‡   c                 C   s>  |dur
t  d|¡ |rt|ƒtkrtdƒ‚t| tjƒr#t|  	¡ ƒ}nt| t
jƒr,t}nt| tjƒr5t}nt| tjƒr>t}ntdƒ‚t|ƒ}tƒ }|rst}t| d }t}t}t d¡}	| |	¡ | |¡ 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|… ƒ}t'|ƒ|||…< |S )z3Serialize private key with OpenSSH custom encoding.Nr   zNPasswords longer than 72 bytes are not supported by OpenSSH private key formatúUnsupported key typer¼   r   rJ   r   rC   r,   ),r   r¾   r3   Ú_MAX_PASSWORDr(   rf   r   ÚEllipticCurvePrivateKeyr*   r)   r
   ÚRSAPrivateKeyÚ_SSH_RSAr   ÚDSAPrivateKeyÚ_SSH_DSAr	   r±   Ú_SSH_ED25519r»   rY   Ú_DEFAULT_CIPHERr8   rÇ   Ú_DEFAULT_ROUNDSÚosÚurandomrk   re   r   r@   rÆ   r“   r•   rb   rÊ   rj   rÅ   rh   ri   rt   Ú	encryptorÚupdate_intor2   )r‡   r   r�   rÓ   Úf_kdfoptionsr9   rÕ   rÎ   r   r   r:   r×   rÐ   ÚcheckvalrÚ   Úf_public_keyÚ	f_secretsÚf_mainÚslenÚmlenrv   ÚofsÚtxtr   r   r   Úserialize_ssh_private_key(  sv   ÿ















 ró   c              	   C   s|  t |ƒ}t d| ¡ t | ¡}|stdƒ‚| d¡ }}| d¡}d}t|ttƒ d… kr9d}|dttƒ … }t	|ƒ}z	t
t |¡ƒ} W n ttjfyT   tdƒ‚w t| ƒ\}} ||krctdƒ‚|rkt| ƒ\}	} | || |¡\}
} |r¸t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ\}} t| ƒ |
S )	z-Load public key from OpenSSH one-line format.r/   zInvalid line formatr   é   FNTzInvalid key format)r   r   r½   Ú_SSH_PUBKEY_RCÚmatchr(   ÚgroupÚ_CERT_SUFFIXr3   r»   rh   rÂ   rÃ   Ú	TypeErrorÚErrorrN   rƒ   rL   rG   r7   )r/   r:   rË   r�   Úorig_key_typeÚkey_bodyÚ	with_certrÓ   Úinner_key_typeÚnoncer)   ÚserialÚcctypeÚkey_idÚ
principalsÚvalid_afterÚvalid_beforeÚcrit_optionsÚ
extensionsÚreservedÚsig_keyÚ	signaturer   r   r   Úload_ssh_public_key…  sJ   

ÿr  r)   c                 C   sš   t | tjƒrt| ƒ}nt | tjƒrt}nt | tjƒrt	}nt | t
jƒr&t}ntdƒ‚t|ƒ}tƒ }| |¡ | | |¡ t | ¡ ¡ ¡ }d |d|g¡S )z&One-line public key format for OpenSSHrÜ   r,   ó    )rf   r   r¥   r*   r
   ÚRSAPublicKeyrà   r   ÚDSAPublicKeyrâ   r	   r¯   rã   r(   r»   rY   rk   r“   rÂ   Ú
b2a_base64ru   Ústripr-   )r)   r�   rÓ   r‘   Úpubr   r   r   Úserialize_ssh_public_key°  s   

r  )FrZ   )hrÂ   ræ   ÚreÚstructÚtypingÚbase64r   r.   Úcryptographyr   Úcryptography.exceptionsr   Úcryptography.hazmat.backendsr   Ú)cryptography.hazmat.primitives.asymmetricr   r   r	   r
   Ú&cryptography.hazmat.primitives.ciphersr   r   r   Ú,cryptography.hazmat.primitives.serializationr   r   r   r   Úbcryptr   r   Ú_bcrypt_supportedÚImportErrorrg   rQ   Úboolrã   rà   râ   Ú_ECDSA_NISTP256Ú_ECDSA_NISTP384Ú_ECDSA_NISTP521rø   Úcompilerõ   rÅ   Ú	_SK_STARTÚ_SK_ENDrÇ   rÆ   rä   rå   rÝ   ÚDOTALLr¿   rh   ri   ÚrangerÊ   ÚAESÚCTRÚCBCr8   r'   ÚStructrE   rK   r*   r2   r5   r7   r@   rG   rL   rN   rT   rX   ÚobjectrY   r|   r˜   r¡   r®   Ú	SECP256R1Ú	SECP384R1Ú	SECP521R1rº   r»   ÚUnionrÞ   rß   rá   r±   Ú_SSH_PRIVATE_KEY_TYPESÚOptionalrÛ   ró   r¥   r  r  r¯   Ú_SSH_PUBLIC_KEY_TYPESr  r  r   r   r   r   Ú<module>   sà   ûÿþýüûúý
þý




0>>=:ú
	ýÿ	ÿÿÿ
þNþÿ
þUýÿ+