3 lá˜_²Tã@sÞddlmZmZmZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl mZddlmZmZmZmZddlmZmZmZddlmZmZmZmZydd lmZd Z Wn e!k rØd Z d d „ZYnXyddl"m#Z$Wn"e!k �r ddl"m%Z$YnXdZ&dZ'dZ(dZ)dZ*dZ+dZ,ej-dƒZ.dZ/dZ0dZ1dZ2dZ3dZ4dZ5dZ6ej-e0d e1ej7ƒZ8e9e:e;d!dSƒƒƒZdfej=d"ej?dfd#œZ@e)e*e+d$œZAejBd%ƒZCejBd&ƒZDd'd(„ZEe0d)e1d)fd*d+„ZFd,d-„ZGd.d/„ZHd0d1„ZId2d3„ZJd4d5„ZKd6d7„ZLd8d9„ZMd:d;„ZNGdd?„d?eOƒZQGd@dA„dAeOƒZRGdBdC„dCeOƒZSGdDdE„dEeOƒZTe'eQƒe(eRƒe&eTƒe)eSdFejUƒƒe*eSdGejVƒƒe+eSdHejWƒƒiZXdIdJ„ZYdTdKdL„ZZdUdMdN„Z[dVdOdP„Z\dQdR„Z]dS)Wé)Úabsolute_importÚdivisionÚprint_functionN)Úutils)ÚUnsupportedAlgorithm)Ú _get_backend)ÚdsaÚecÚed25519Úrsa)ÚCipherÚ algorithmsÚmodes)ÚEncodingÚ NoEncryptionÚ PrivateFormatÚ PublicFormat)ÚkdfTFcOs tdƒ‚dS)NzNeed bcrypt module)r)ÚargsÚkwargs©rú/usr/lib64/python3.6/ssh.pyÚ _bcrypt_kdf!sr)Ú encodebytes)Ú encodestrings ssh-ed25519sssh-rsasssh-dsssecdsa-sha2-nistp256secdsa-sha2-nistp384secdsa-sha2-nistp521s-cert-v01@openssh.coms\A(\S+)[ \t]+(\S+)sopenssh-key-v1s#-----BEGIN OPENSSH PRIVATE KEY-----s!-----END OPENSSH PRIVATE KEY-----sbcryptsnones aes256-ctrééHs(.*?)éé )s aes256-ctrs aes256-cbc)Z secp256r1Z secp384r1Z secp521r1s>Is>QcCs(|j}|jtkrtd|jƒ‚t|jS)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_keyrrrrÚ_ecdsa_key_typeSs   r$ó cCsdj|t|ƒ|gƒS)Nó)ÚjoinÚ_base64_encode)ÚdataÚprefixÚsuffixrrrÚ_ssh_pem_encode]sr,cCs"| st|ƒ|dkrtdƒ‚dS)zRequire data to be full blocksrzCorrupt data: missing paddingN)Úlenr")r)Z block_lenrrrÚ_check_block_sizeasr.cCs|r tdƒ‚dS)z!All data should have been parsed.zCorrupt data: unparsed dataN)r")r)rrrÚ _check_emptygsr/c CsT|s tdƒ‚t|\}}}}t|||||dƒ} t|| d|…ƒ|| |d…ƒ|ƒS)z$Generate key + iv and return cipher.zKey is password-protected.TN)r"Ú _SSH_CIPHERSrr ) Ú ciphernameÚpasswordÚsaltÚroundsÚbackendZalgoZkey_lenÚmodeZiv_lenZseedrrrÚ _init_cipherms r7cCs6t|ƒdkrtdƒ‚tj|dd…ƒd|dd…fS)ZUint32éz Invalid dataNr)r-r"Ú_U32Úunpack)r)rrrÚ_get_u32ws r;cCs6t|ƒdkrtdƒ‚tj|dd…ƒd|dd…fS)ZUint64éz Invalid dataNr)r-r"Ú_U64r:)r)rrrÚ_get_u64~s r>cCs8t|ƒ\}}|t|ƒkr tdƒ‚|d|…||d…fS)zBytes with u32 length prefixz Invalid dataN)r;r-r")r)ÚnrrrÚ _get_sshstr…s  r@cCs8t|ƒ\}}|r(tj|dƒdkr(tdƒ‚tj|dƒ|fS)z Big integer.réz Invalid dataZbig)r@ÚsixÚ indexbytesr"rZint_from_bytes)r)ÚvalrrrÚ _get_mpint�s rEcCs4|dkrtdƒ‚|sdS|jƒdd}tj||ƒS)z!Storage format for signed bigint.rznegative mpint not allowedr&r<)r"Ú bit_lengthrZ int_to_bytes)rDÚnbytesrrrÚ _to_mpint•s rHc@sTeZdZdZddd„Zdd„Zdd„Zd d „Zd d „Zd d„Z ddd„Z dd„Z dS)Ú _FragListz,Build recursive structure without data copy.NcCsg|_|r|jj|ƒdS)N)ÚflistÚextend)ÚselfZinitrrrÚ__init__¢sz_FragList.__init__cCs|jj|ƒdS)zAdd plain bytesN)rJÚappend)rLrDrrrÚput_raw§sz_FragList.put_rawcCs|jjtj|ƒƒdS)zBig-endian uint32N)rJrNr9Úpack)rLrDrrrÚput_u32«sz_FragList.put_u32cCsLt|tttfƒr,|jt|ƒƒ|jj|ƒn|j|jƒƒ|jj |jƒdS)zBytes prefixed with u32 lengthN) Ú isinstanceÚbytesÚ memoryviewÚ bytearrayrQr-rJrNÚsizerK)rLrDrrrÚ put_sshstr¯s z_FragList.put_sshstrcCs|jt|ƒƒdS)z*Big-endian bigint prefixed with u32 lengthN)rWrH)rLrDrrrÚ put_mpint¸sz_FragList.put_mpintcCsttt|jƒƒS)zCurrent number of bytes)ÚsumÚmapr-rJ)rLrrrrV¼sz_FragList.sizercCs6x0|jD]&}t|ƒ}|||}}||||…<qW|S)zWrite into bytearray)rJr-)rLZdstbufÚposZfragZflenÚstartrrrÚrenderÀs  z_FragList.rendercCs"tt|jƒƒƒ}|j|ƒ|jƒS)zReturn as bytes)rTrUrVr]Útobytes)rLÚbufrrrr^Ès z_FragList.tobytes)N)r) Ú__name__Ú __module__Ú __qualname__Ú__doc__rMrOrQrWrXrVr]r^rrrrrIŸs   rIc@s8eZdZdZdd„Zdd„Zdd„Zdd „Zd d „Zd S) Ú _SSHFormatRSAzhFormat for RSA keys. Public: mpint e, n Private: mpint n, e, d, iqmp, p, q cCs$t|ƒ\}}t|ƒ\}}||f|fS)zRSA public fields)rE)rLr)Úer?rrrÚ get_publicØs  z_SSHFormatRSA.get_publiccCs0|j|ƒ\\}}}tj||ƒ}|j|ƒ}||fS)zMake RSA public key from data.)rfr ÚRSAPublicNumbersr#)rLÚkey_typer)r5rer?Úpublic_numbersr#rrrÚ load_publicÞs  z_SSHFormatRSA.load_publiccCs¨t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\} }||f|kr\tdƒ‚tj||ƒ} tj|| ƒ} tj||ƒ} tj|| || | || ƒ} | j|ƒ}||fS)zMake RSA private key from data.z Corrupt data: rsa field mismatch)rEr"r Z rsa_crt_dmp1Z rsa_crt_dmq1rgZRSAPrivateNumbersÚ private_key)rLr)Ú pubfieldsr5r?reÚdÚiqmpÚpÚqZdmp1Zdmq1riÚprivate_numbersrkrrrÚ load_privateås           z_SSHFormatRSA.load_privatecCs$|jƒ}|j|jƒ|j|jƒdS)zWrite RSA public keyN)rirXrer?)rLr#Úf_pubZpubnrrrÚ encode_publicùs z_SSHFormatRSA.encode_publiccCsZ|jƒ}|j}|j|jƒ|j|jƒ|j|jƒ|j|jƒ|j|jƒ|j|jƒdS)zWrite RSA private keyN) rqrirXr?rermrnrorp)rLrkÚf_privrqrirrrÚencode_privateÿs     z_SSHFormatRSA.encode_privateN) r`rarbrcrfrjrrrtrvrrrrrdÏs rdc@s@eZdZdZdd„Zdd„Zdd„Zdd „Zd d „Zd d „Z dS)Ú _SSHFormatDSAzhFormat for DSA keys. Public: mpint p, q, g, y Private: mpint p, q, g, y, x cCs@t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\}}||||f|fS)zDSA public fields)rE)rLr)rorpÚgÚyrrrrfs     z_SSHFormatDSA.get_publicc CsL|j|ƒ\\}}}}}tj|||ƒ}tj||ƒ} |j| ƒ| j|ƒ} | |fS)zMake DSA public key from data.)rfrÚDSAParameterNumbersÚDSAPublicNumbersÚ _validater#) rLrhr)r5rorprxryÚparameter_numbersrir#rrrrjs    z_SSHFormatDSA.load_publicc Cs||j|ƒ\\}}}}}t|ƒ\}}||||f|kr:tdƒ‚tj|||ƒ} tj|| ƒ} |j| ƒtj|| ƒ} | j|ƒ} | |fS)zMake DSA private key from data.z Corrupt data: dsa field mismatch) rfrEr"rrzr{r|ZDSAPrivateNumbersrk) rLr)rlr5rorprxryÚxr}rirqrkrrrrr's     z_SSHFormatDSA.load_privatecCsL|jƒ}|j}|j|ƒ|j|jƒ|j|jƒ|j|jƒ|j|jƒdS)zWrite DSA public keyN)rir}r|rXrorprxry)rLr#rsrir}rrrrt5s    z_SSHFormatDSA.encode_publiccCs$|j|jƒ|ƒ|j|jƒjƒdS)zWrite DSA private keyN)rtr#rXrqr~)rLrkrurrrrv@sz_SSHFormatDSA.encode_privatecCs |j}|jjƒdkrtdƒ‚dS)Niz#SSH supports only 1024 bit DSA keys)r}rorFr")rLrir}rrrr|Esz_SSHFormatDSA._validateN) r`rarbrcrfrjrrrtrvr|rrrrrw s  rwc@s@eZdZdZdd„Zdd„Zdd„Zdd „Zd d „Zd d „Z dS)Ú_SSHFormatECDSAz–Format for ECDSA keys. Public: str curve bytes point Private: str curve bytes point mpint secret cCs||_||_dS)N)Ússh_curve_namer)rLr€rrrrrMWsz_SSHFormatECDSA.__init__cCsNt|ƒ\}}t|ƒ\}}||jkr*tdƒ‚tj|dƒdkrBtdƒ‚||f|fS)zECDSA public fieldszCurve name mismatchrr8zNeed uncompressed point)r@r€r"rBrCÚNotImplementedError)rLr)rÚpointrrrrf[s   z_SSHFormatECDSA.get_publiccCs.|j|ƒ\\}}}tjj|j|jƒƒ}||fS)z Make ECDSA public key from data.)rfr ÚEllipticCurvePublicKeyZfrom_encoded_pointrr^)rLrhr)r5Ú curve_namer‚r#rrrrjesz_SSHFormatECDSA.load_publiccCsJ|j|ƒ\\}}}t|ƒ\}}||f|kr2tdƒ‚tj||j|ƒ}||fS)z!Make ECDSA private key from data.z"Corrupt data: ecdsa field mismatch)rfrEr"r Zderive_private_keyr)rLr)rlr5r„r‚Úsecretrkrrrrrms   z_SSHFormatECDSA.load_privatecCs*|jtjtjƒ}|j|jƒ|j|ƒdS)zWrite ECDSA public keyN)Ú public_bytesrZX962rZUncompressedPointrWr€)rLr#rsr‚rrrrtws  z_SSHFormatECDSA.encode_publiccCs,|jƒ}|jƒ}|j||ƒ|j|jƒdS)zWrite ECDSA private keyN)r#rqrtrXZ private_value)rLrkrur#rqrrrrvs z_SSHFormatECDSA.encode_privateN) r`rarbrcrMrfrjrrrtrvrrrrrKs   rc@s8eZdZdZdd„Zdd„Zdd„Zdd „Zd d „Zd S) Ú_SSHFormatEd25519z~Format for Ed25519 keys. Public: bytes point Private: bytes point bytes secret_and_point cCst|ƒ\}}|f|fS)zEd25519 public fields)r@)rLr)r‚rrrrf’s z_SSHFormatEd25519.get_publiccCs(|j|ƒ\\}}tjj|jƒƒ}||fS)z"Make Ed25519 public key from data.)rfr ÚEd25519PublicKeyZfrom_public_bytesr^)rLrhr)r5r‚r#rrrrj—s z_SSHFormatEd25519.load_publicc Csb|j|ƒ\\}}t|ƒ\}}|dd…}|dd…}||ksF|f|krNtdƒ‚tjj|ƒ}||fS)z#Make Ed25519 private key from data.Nrz$Corrupt data: ed25519 field mismatch)rfr@r"r ÚEd25519PrivateKeyZfrom_private_bytes) rLr)rlr5r‚Zkeypairr…Zpoint2rkrrrrrŸs    z_SSHFormatEd25519.load_privatecCs|jtjtjƒ}|j|ƒdS)zWrite Ed25519 public keyN)r†rÚRawrrW)rLr#rsÚraw_public_keyrrrrt«s z_SSHFormatEd25519.encode_publiccCsR|jƒ}|jtjtjtƒƒ}|jtjtjƒ}t||gƒ}|j ||ƒ|j |ƒdS)zWrite Ed25519 private keyN) r#Z private_bytesrrŠrrr†rrIrtrW)rLrkrur#Zraw_private_keyr‹Z f_keypairrrrrv²s   z _SSHFormatEd25519.encode_privateN) r`rarbrcrfrjrrrtrvrrrrr‡ˆs  r‡snistp256snistp384snistp521cCs6t|tƒst|ƒjƒ}|tkr&t|Std|ƒ‚dS)z"Return valid format or throw errorzUnsupported key type: %rN)rRrSrTr^Ú _KEY_FORMATSr)rhrrrÚ_lookup_kformatËs   r�cCsRtjd|ƒt|ƒ}|dk r(tjd|ƒtj|ƒ}|s>tdƒ‚|jdƒ}|jdƒ}t j t |ƒ||…ƒ}|j t ƒsztdƒ‚t |ƒtt ƒd…}t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\} }| dkrÎtdƒ‚t|ƒ\} }t| ƒ\} } t| ƒ} | j| ƒ\} } t| ƒt|ƒ\}}t|ƒ||fttfk�r¼|jƒ}|tk�rHtd|ƒ‚|tk�r^td|ƒ‚t|d }t||ƒt|ƒ\}}t|ƒ\}}t|ƒt|||jƒ||ƒ}t |jƒj|ƒƒ}nd }t||ƒt|ƒ\}}t|ƒ\}}||k�rôtd ƒ‚t|ƒ\}}|| k�rtd ƒ‚| j|| |ƒ\}}t|ƒ\}}|tdt|ƒ…k�rNtd ƒ‚|S)z.Load private key from OpenSSH custom encoding.r)Nr2zNot OpenSSH private key formatrzOnly one key supportedzUnsupported cipher: %rzUnsupported KDF: %rér<zCorrupt data: broken checksumzCorrupt data: key type mismatchzCorrupt data: invalid padding)rÚ_check_byteslikerÚ _check_bytesÚ_PEM_RCÚsearchr"r\ÚendÚbinasciiÚ a2b_base64rTÚ startswithÚ _SK_MAGICr-r@r;r�rfr/Ú_NONEr^r0rÚ_BCRYPTr.r7Z decryptorÚupdaterrÚ_PADDING)r)r2r5ÚmZp1Zp2r1ÚkdfnameZ kdfoptionsÚnkeysZpubdataZ pub_key_typeÚkformatrlZedataÚblklenr3Zkbufr4ÚciphZck1Zck2rhrkÚcommentrrrÚload_ssh_private_keyÔsl                            r£cCs>|dk rtjd|ƒ|r,t|ƒtkr,tdƒ‚t|tjƒrFt|j ƒƒ}n>t|t j ƒrXt }n,t|t jƒrjt}nt|tjƒr|t}ntdƒ‚t|ƒ}tƒ}|ræt}t|d}t}t}tjdƒ} |j| ƒ|j|ƒtdƒ} t||| || ƒ} nt}}d}d} d} tjd ƒ} d }tƒ}|j|ƒ|j |j ƒ|ƒt| | gƒ}|j|ƒ|j!||ƒ|j|ƒ|j"t#d||j$ƒ|…ƒtƒ}|j"t%ƒ|j|ƒ|j|ƒ|j|ƒ|j| ƒ|j|ƒ|j|ƒ|j$ƒ}|j$ƒ}t&t'||ƒƒ}|j(|ƒ||}| dk �r| j)ƒj*|||…||d…ƒt+|d|…ƒ}t'|ƒ|||…<|S) z3Serialize private key with OpenSSH custom encoding.Nr2zNPasswords longer than 72 bytes are not supported by OpenSSH private key formatzUnsupported key typerŽrr<rr8r&),rr�r-Ú _MAX_PASSWORDr"rRr ZEllipticCurvePrivateKeyr$r#r Z RSAPrivateKeyÚ_SSH_RSArZ DSAPrivateKeyÚ_SSH_DSAr r‰Ú _SSH_ED25519r�rIÚ_DEFAULT_CIPHERr0r™Ú_DEFAULT_ROUNDSÚosÚurandomrWrQrr7r˜rtrvrOr›rVr—rTrUr]Z encryptorZ update_intor,)rkr2rhrŸZ f_kdfoptionsr1r r�r4r3r5r¡ržZcheckvalr¢Z f_public_keyZ f_secretsZf_mainZslenZmlenr_ZofsZtxtrrrÚserialize_ssh_private_keyst                         r¬c Cs„t|ƒ}tjd|ƒtj|ƒ}|s*tdƒ‚|jdƒ}}|jdƒ}d}t|ttƒ d…krrd}|dttƒ …}t |ƒ}yt t j |ƒƒ}Wn"t t jfk r®tdƒ‚YnXt|ƒ\}}||krÌtdƒ‚|rÜt|ƒ\} }|j|||ƒ\} }|�rxt|ƒ\} }t|ƒ\} }t|ƒ\} }t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ\}}t|ƒ| S) z-Load public key from OpenSSH one-line format.r)zInvalid line formatréFNTzInvalid key format)rrr�Ú_SSH_PUBKEY_RCÚmatchr"ÚgroupÚ _CERT_SUFFIXr-r�rTr”r•Ú TypeErrorÚErrorr@rjr>r;r/)r)r5rœrhZ orig_key_typeZkey_bodyZ with_certrŸZinner_key_typeZnoncer#ÚserialZcctypeZkey_idZ principalsZ valid_afterZ valid_beforeZ crit_optionsÚ extensionsZreservedZsig_keyZ signaturerrrÚload_ssh_public_keymsH                r¶cCsšt|tjƒrt|ƒ}n>t|tjƒr(t}n,t|tjƒr:t }nt|t j ƒrLt }nt dƒ‚t|ƒ}tƒ}|j|ƒ|j||ƒtj|jƒƒjƒ}dj|d|gƒS)z&One-line public key format for OpenSSHzUnsupported key typer&ó )rRr rƒr$r Z RSAPublicKeyr¥rZ DSAPublicKeyr¦r rˆr§r"r�rIrWrtr”Z b2a_base64r^Ústripr')r#rhrŸrsZpubrrrÚserialize_ssh_public_key˜s       r¹é)N)N)N)^Z __future__rrrr”rªÚreÚstructrBZ cryptographyrZcryptography.exceptionsrZcryptography.hazmat.backendsrZ)cryptography.hazmat.primitives.asymmetricrr r r Z&cryptography.hazmat.primitives.ciphersr r rZ,cryptography.hazmat.primitives.serializationrrrrZbcryptrrZ_bcrypt_supportedÚ ImportErrorÚbase64rr(rr§r¥r¦Z_ECDSA_NISTP256Z_ECDSA_NISTP384Z_ECDSA_NISTP521r±Úcompiler®r—Z _SK_STARTZ_SK_ENDr™r˜r¨r©r¤ÚDOTALLr‘rTrUÚranger›ZAESZCTRZCBCr0r!ÚStructr9r=r$r,r.r/r7r;r>r@rErHÚobjectrIrdrwrr‡Z SECP256R1Z SECP384R1Z SECP521R1rŒr�r£r¬r¶r¹rrrrÚs�          0>>=: J O +