a
     `T                     @   s  d dl mZmZ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	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!y   dZ dd ZY n0 zd dl"m#Z$ W n  e!y   d dl"m%Z$ Y n0 dZ&dZ'dZ(dZ)dZ*dZ+dZ,e-dZ.dZ/dZ0dZ1dZ2dZ3dZ4dZ5dZ6e-e0d  e1 ej7Z8e9e:e;d!d"Z<ej=d#ej>dfej=d#ej?dfd$Z@e)e*e+d%ZAeBd&ZCeBd'ZDd(d) ZEe0d* e1d* fd+d,ZFd-d. ZGd/d0 ZHd1d2 ZId3d4 ZJd5d6 ZKd7d8 ZLd9d: ZMd;d< ZNG d=d> d>eOZPG d?d@ d@eOZQG dAdB dBeOZRG dCdD dDeOZSG dEdF dFeOZTe'eQ e(eR e&eT e)eSdGeU e*eSdHeV e+eSdIeW iZXdJdK ZYdTdLdMZZdUdNdOZ[dVdPdQZ\dRdS Z]dS )W    )absolute_importdivisionprint_functionN)utilsUnsupportedAlgorithm)_get_backend)dsaeced25519rsa)Cipher
algorithmsmodes)EncodingNoEncryptionPrivateFormatPublicFormat)kdfTFc                  O   s   t dd S )NzNeed bcrypt moduler   )argskwargs r   R/usr/lib/python3/dist-packages/cryptography/hazmat/primitives/serialization/ssh.py_bcrypt_kdf!   s    r   )encodebytes)encodestrings   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)Z	secp256r1Z	secp384r1Z	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    r/   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,   Z	block_lenr   r   r   _check_block_sizea   s    r1   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    r3   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   )

ciphernamepasswordsaltroundsbackendZalgoZkey_lenmodeZiv_lenZseedr   r   r   _init_cipherm   s
    r;   c                 C   s6   t | dk rtdt| dd d | dd fS )ZUint32   Invalid dataNr   )r0   r%   _U32unpackr2   r   r   r   _get_u32w   s    r@   c                 C   s6   t | dk rtdt| dd d | dd fS )ZUint64   r=   Nr   )r0   r%   _U64r?   r2   r   r   r   _get_u64~   s    rC   c                 C   s8   t | \}} |t| kr td| d| | |d fS )zBytes with u32 length prefixr=   N)r@   r0   r%   )r,   nr   r   r   _get_sshstr   s    rE   c                 C   s8   t | \}} |r(t|ddkr(tdt|d| fS )zBig integer.r      r=   Zbig)rE   six
indexbytesr%   r   Zint_from_bytes)r,   valr   r   r   
_get_mpint   s    rJ   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)   rA   )r%   
bit_lengthr   Zint_to_bytes)rI   nbytesr   r   r   	_to_mpint   s    rM   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 N)flistextend)selfZinitr   r   r   __init__   s    z_FragList.__init__c                 C   s   | j | dS )zAdd plain bytesN)rP   appendrR   rI   r   r   r   put_raw   s    z_FragList.put_rawc                 C   s   | j t| dS )zBig-endian uint32N)rP   rT   r>   ZpackrU   r   r   r   put_u32   s    z_FragList.put_u32c                 C   sL   t |tttfr,| t| | j| n| |  | j	|j dS )zBytes prefixed with u32 lengthN)

isinstancebytes
memoryview	bytearrayrW   r0   rP   rT   sizerQ   rU   r   r   r   
put_sshstr   s
    z_FragList.put_sshstrc                 C   s   |  t| dS )z*Big-endian bigint prefixed with u32 lengthN)r]   rM   rU   r   r   r   	put_mpint   s    z_FragList.put_mpintc                 C   s   t tt| jS )zCurrent number of bytes)summapr0   rP   )rR   r   r   r   r\      s    z_FragList.sizer   c                 C   s2   | j D ]&}t|}|||  }}||||< q|S )zWrite into bytearray)rP   r0   )rR   ZdstbufposZfragZflenstartr   r   r   render   s
    
z_FragList.renderc                 C   s"   t t|  }| | | S )zReturn as bytes)rZ   r[   r\   rc   tobytes)rR   bufr   r   r   rd      s    
z_FragList.tobytes)N)r   )__name__
__module____qualname____doc__rS   rV   rW   r]   r^   r\   rc   rd   r   r   r   r   rN      s   
	
rN   c                   @   s8   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rJ   )rR   r,   erD   r   r   r   
get_public   s    z_SSHFormatRSA.get_publicc                 C   s0   |  |\\}}}t||}||}||fS )zMake RSA public key from data.)rm   r   RSAPublicNumbersr&   )rR   key_typer,   r9   rl   rD   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)rJ   r%   r   Zrsa_crt_dmp1Zrsa_crt_dmq1rn   ZRSAPrivateNumbersprivate_key)rR   r,   	pubfieldsr9   rD   rl   diqmppqZdmp1Zdmq1rp   private_numbersrr   r   r   r   load_private   s     
z_SSHFormatRSA.load_privatec                 C   s$   |  }||j ||j dS )zWrite RSA public keyN)rp   r^   rl   rD   )rR   r&   f_pubZ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)	rx   rp   r^   rD   rl   rt   ru   rv   rw   )rR   rr   f_privrx   rp   r   r   r   encode_private   s    z_SSHFormatRSA.encode_privateN	rf   rg   rh   ri   rm   rq   ry   r{   r}   r   r   r   r   rj      s   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	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 fieldsrk   )rR   r,   rv   rw   gyr   r   r   rm     s
    z_SSHFormatDSA.get_publicc                 C   sL   |  |\\}}}}}t|||}t||}	| |	 |	|}
|
|fS )zMake DSA public key from data.)rm   r	   DSAParameterNumbersDSAPublicNumbers	_validater&   )rR   ro   r,   r9   rv   rw   r   r   parameter_numbersrp   r&   r   r   r   rq     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)	rm   rJ   r%   r	   r   r   r   ZDSAPrivateNumbersrr   )rR   r,   rs   r9   rv   rw   r   r   xr   rp   rx   rr   r   r   r   ry   '  s    

z_SSHFormatDSA.load_privatec                 C   sL   |  }|j}| | ||j ||j ||j ||j dS )zWrite DSA public keyN)rp   r   r   r^   rv   rw   r   r   )rR   r&   rz   rp   r   r   r   r   r{   5  s    
z_SSHFormatDSA.encode_publicc                 C   s$   |  | | || j dS )zWrite DSA private keyN)r{   r&   r^   rx   r   )rR   rr   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   rv   rK   r%   )rR   rp   r   r   r   r   r   E  s    z_SSHFormatDSA._validateN)
rf   rg   rh   ri   rm   rq   ry   r{   r}   r   r   r   r   r   r     s   	r   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	dS )_SSHFormatECDSAzFormat for ECDSA keys.

    Public:
        str curve
        bytes point
    Private:
        str curve
        bytes point
        mpint secret
    c                 C   s   || _ || _d S rO   )ssh_curve_namer"   )rR   r   r"   r   r   r   rS   W  s    z_SSHFormatECDSA.__init__c                 C   sN   t |\}}t |\}}|| jkr*tdt|ddkrBtd||f|fS )zECDSA public fieldszCurve name mismatchr   r<   zNeed uncompressed point)rE   r   r%   rG   rH   NotImplementedError)rR   r,   r"   pointr   r   r   rm   [  s    
z_SSHFormatECDSA.get_publicc                 C   s.   |  |\\}}}tj| j| }||fS )z Make ECDSA public key from data.)rm   r
   EllipticCurvePublicKeyZfrom_encoded_pointr"   rd   )rR   ro   r,   r9   
curve_namer   r&   r   r   r   rq   e  s
    
z_SSHFormatECDSA.load_publicc                 C   sJ   |  |\\}}}t|\}}||f|kr2tdt|| j|}||fS )z!Make ECDSA private key from data.z"Corrupt data: ecdsa field mismatch)rm   rJ   r%   r
   Zderive_private_keyr"   )rR   r,   rs   r9   r   r   secretrr   r   r   r   ry   m  s    z_SSHFormatECDSA.load_privatec                 C   s*   | tjtj}|| j || dS )zWrite ECDSA public keyN)public_bytesr   ZX962r   ZUncompressedPointr]   r   )rR   r&   rz   r   r   r   r   r{   w  s
    z_SSHFormatECDSA.encode_publicc                 C   s,   |  }| }| || ||j dS )zWrite ECDSA private keyN)r&   rx   r{   r^   Zprivate_value)rR   rr   r|   r&   rx   r   r   r   r}     s    z_SSHFormatECDSA.encode_privateN)
rf   rg   rh   ri   rS   rm   rq   ry   r{   r}   r   r   r   r   r   K  s   

r   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )_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)rE   )rR   r,   r   r   r   r   rm     s    z_SSHFormatEd25519.get_publicc                 C   s(   |  |\\}}tj| }||fS )z"Make Ed25519 public key from data.)rm   r   Ed25519PublicKeyZfrom_public_bytesrd   )rR   ro   r,   r9   r   r&   r   r   r   rq     s
    z_SSHFormatEd25519.load_publicc           	      C   sb   |  |\\}}t|\}}|dd }|dd }||ksF|f|krNtdtj|}||fS )z#Make Ed25519 private key from data.Nr!   z$Corrupt data: ed25519 field mismatch)rm   rE   r%   r   Ed25519PrivateKeyZfrom_private_bytes)	rR   r,   rs   r9   r   Zkeypairr   Zpoint2rr   r   r   r   ry     s    z_SSHFormatEd25519.load_privatec                 C   s   | tjtj}|| dS )zWrite Ed25519 public keyN)r   r   Rawr   r]   )rR   r&   rz   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&   Zprivate_bytesr   r   r   r   r   r   rN   r{   r]   )rR   rr   r|   r&   Zraw_private_keyr   Z	f_keypairr   r   r   r}     s    z _SSHFormatEd25519.encode_privateNr~   r   r   r   r   r     s   	r   s   nistp256s   nistp384s   nistp521c                 C   s6   t | tst|  } | tv r&t|  S td|  dS )z"Return valid format or throw errorzUnsupported key type: %rN)rX   rY   rZ   rd   _KEY_FORMATSr   )ro   r   r   r   _lookup_kformat  s
    
r   c                 C   sR  t d|  t|}|dur(t d| t| }|s>td|d}|d}t	
t| || } | tsztdt| ttd } t| \}} t| \}} t| \}} t| \}	} |	dkrtdt| \}
} t|
\}}
t|}||
\}}
t|
 t| \}} t|  ||fttfkr| }|tvrHtd| |tkr^td| t| d	 }t|| t|\}}t|\}}t| t||| ||}t| |}nd
}t|| t|\}}t|\}}||krtdt|\}}||krtd||||\}}t|\}}|tdt| krNtd|S )z.Load private key from OpenSSH custom encoding.r,   Nr6   zNot OpenSSH private key formatr   zOnly one key supportedzUnsupported cipher: %rzUnsupported KDF: %r   rA   zCorrupt data: broken checksumzCorrupt data: key type mismatchzCorrupt data: invalid padding)r   _check_bytesliker   _check_bytes_PEM_RCsearchr%   rb   endbinascii
a2b_base64rZ   
startswith	_SK_MAGICr0   rE   r@   r   rm   r3   _NONErd   r4   r   _BCRYPTr1   r;   Z	decryptorupdatery   _PADDING)r,   r6   r9   mZp1Zp2r5   kdfnameZ
kdfoptionsnkeysZpubdataZpub_key_typekformatrs   Zedatablklenr7   Zkbufr8   ciphZck1Zck2ro   rr   commentr   r   r   load_ssh_private_key  sn    









r   c                 C   s>  |durt d| |r,t|tkr,tdt| tjrFt| 	 }n>t| t
jrXt}n,t| tjrjt}nt| tjr|t}ntdt|}t }|rt}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.Nr6   zNPasswords longer than 72 bytes are not supported by OpenSSH private key formatUnsupported key typer   r   rA   r   r<   r)   ),r   r   r0   _MAX_PASSWORDr%   rX   r
   ZEllipticCurvePrivateKeyr'   r&   r   ZRSAPrivateKey_SSH_RSAr	   ZDSAPrivateKey_SSH_DSAr   r   _SSH_ED25519r   rN   _DEFAULT_CIPHERr4   r   _DEFAULT_ROUNDSosurandomr]   rW   r   r;   r   r{   r}   rV   r   r\   r   rZ   r[   rc   Z	encryptorZupdate_intor/   )rr   r6   ro   r   Zf_kdfoptionsr5   r   r   r8   r7   r9   r   r   Zcheckvalr   Zf_public_keyZ	f_secretsZf_mainZslenZmlenre   ZofsZ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rrd}|dtt  }t	|}zt
t|} W n  ttjfy   tdY n0 t| \}} ||krtd|rt| \}	} ||| |\}
} |rvt| \}} 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_SUFFIXr0   r   rZ   r   r   	TypeErrorErrorrE   rq   rC   r@   r3   )r,   r9   r   ro   Zorig_key_typeZkey_bodyZ	with_certr   Zinner_key_typeZnoncer&   serialZcctypeZkey_idZ
principalsZvalid_afterZvalid_beforeZcrit_options
extensionsZreservedZsig_keyZ	signaturer   r   r   load_ssh_public_keym  sH    

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rLt}ntdt|}t }|| || | t|  }d|d|gS )z&One-line public key format for OpenSSHr   r)       )rX   r
   r   r'   r   ZRSAPublicKeyr   r	   ZDSAPublicKeyr   r   r   r   r%   r   rN   r]   r{   r   Z
b2a_base64rd   stripr*   )r&   ro   r   rz   Zpubr   r   r   serialize_ssh_public_key  s    

r   )N)N)N)^Z
__future__r   r   r   r   r   reZstructrG   Zcryptographyr   Zcryptography.exceptionsr   Zcryptography.hazmat.backendsr   Z)cryptography.hazmat.primitives.asymmetricr	   r
   r   r   Z&cryptography.hazmat.primitives.ciphersr   r   r   Z,cryptography.hazmat.primitives.serializationr   r   r   r   Zbcryptr   r   Z_bcrypt_supportedImportErrorbase64r   r+   r   r   r   r   Z_ECDSA_NISTP256Z_ECDSA_NISTP384Z_ECDSA_NISTP521r   compiler   r   Z	_SK_STARTZ_SK_ENDr   r   r   r   r   DOTALLr   rZ   r[   ranger   ZAESZCTRZCBCr4   r$   ZStructr>   rB   r'   r/   r1   r3   r;   r@   rC   rE   rJ   rM   objectrN   rj   r   r   r   Z	SECP256R1Z	SECP384R1Z	SECP521R1r   r   r   r   r   r   r   r   r   r   <module>   s   





0>>=:
	
J
O
+