o
    >hfk                     @  s   d Z ddlm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mZ ddlmZ dd	lmZ dd
lmZ edrkddlmZmZmZmZmZmZ ddl m!Z!m"Z"m#Z#m$Z$ ndZ%dddZ&G dd deZ'dS )z-
Tests for L{twisted.conch.scripts.ckeygen}.
    )annotationsN)StringIO)Callable)NoReturn)privateECDSA_opensshprivateEd25519_openssh_newprivateRSA_opensshprivateRSA_openssh_encryptedpublicRSA_openssh)FilePath)requireModule)TestCasecryptography)_getKeyOrDefault_saveKeychangePassPhrasedisplayPublicKeyenumrepresentationprintFingerprint)BadFingerPrintFormatBadKeyErrorFingerprintFormatsKeyz7cryptography required for twisted.conch.scripts.ckeygenpassphrasesstrreturnCallable[[object], str]c                    s   t |  d fdd}|S )	a@  
    Return a callable to patch C{getpass.getpass}.  Yields a passphrase each
    time called. Use case is to provide an old, then new passphrase(s) as if
    requested interactively.

    @param passphrases: The list of passphrases returned, one per each call.

    @return: A callable to patch C{getpass.getpass}.
    _objectr   r   c                   s   t  S N)nextr   passphrasesIter /var/www/vedio/testing/chatpythonscript.ninositsolution.com/env/lib/python3.10/site-packages/twisted/conch/test/test_ckeygen.pyfakeGetpass<      z makeGetpass.<locals>.fakeGetpassN)r   r   r   r   )iter)r   r&   r$   r"   r%   makeGetpass0   s   
r)   c                   @  s  e Zd ZdZdZddZ		d[d\ddZdZddZdZddZdZddZdZddZ	dZddZ
dZddZdZddZdZddZdZddZdZd d!ZdZd"d#ZdZd$d%ZdZd&d'ZdZd(d)ZdZd*d+ZdZd,d-ZdZd.d/ZdZd0d1ZdZd2d3ZdZd4d5ZdZd6d7ZdZd8d9ZdZd:d;ZdZd<d=ZdZd>d?ZdZd@dAZdZdBdCZ dZdDdEZ!dZdFdGZ"dZdHdIZ#dZdJdKZ$dZdLdMZ%dZdNdOZ&dZdPdQZ'dZdRdSZ(dZdTdUZ)dZdVdWZ*dZdXdYZ+dS )]KeyGenTestszN
    Tests for various functions used to implement the I{ckeygen} script.
    r   Nonec                 C  s   t  | _| td| j dS )zX
        Patch C{sys.stdout} so tests can make assertions about what's printed.
        stdoutN)r   r,   patchsysselfr$   r$   r%   setUpG   s   zKeyGenTests.setUpNkeyTyper   keySize
str | NoneprivateKeySubtypec                 C  s   |   }dd|d|dg}|d ur|d|g |d ur"|d|g t| t|}t|d }|dkr@| | d	 n|d
krM| | d n
| | |  | 	|
  d S )Nckeygen-t-fz--no-passphrasez-bz--private-key-subtype.pubecdsaECed25519Ed25519)mktempextend
subprocesscallr   fromFileassertEqualtypeupper
assertTrueisPublic)r0   r2   r3   r5   filenameargsprivKeypubKeyr$   r$   r%   _testrunN   s   

zKeyGenTests._testrunc                 C  s   |  dd | j dddd |  d | j ddd |  d |  dd | j dddd |  d | j ddd |  dd | j dddd |  d | j ddd d S )	Nr:   384v1)r5   r<   dsa2048rsa)rL   r/   r$   r$   r%   test_keygeneratione   s   



zKeyGenTests.test_keygenerationc                 C  sN   |   }| tj tdddd|g W d    d S 1 s w   Y  d S )Nr6   r7   foor8   )r>   assertRaisesr@   CalledProcessError
check_callr0   rH   r$   r$   r%   test_runBadKeytypet   s   "zKeyGenTests.test_runBadKeytypec                 C  "   t ddi}| |d tj dS )z
        L{enumrepresentation} takes a dictionary as input and returns a
        dictionary with its attributes changed to enum representation.
        formatmd5-hexN)r   assertIsr   MD5_HEXr0   optionsr$   r$   r%   test_enumrepresentationy   s   z#KeyGenTests.test_enumrepresentationc                 C  rY   )zF
        Test for format L{FingerprintFormats.SHA256-BASE64}.
        rZ   sha256-base64N)r   r\   r   SHA256_BASE64r^   r$   r$   r%   test_enumrepresentationsha256   s   z)KeyGenTests.test_enumrepresentationsha256c                 C  sN   |  t}tddi W d   n1 sw   Y  | d|jjd  dS )z9
        Test for unsupported fingerprint format
        rZ   
sha-base64N*Unsupported fingerprint format: sha-base64r   )rT   r   r   rC   	exceptionrI   )r0   emr$   r$   r%    test_enumrepresentationBadFormat   s   z,KeyGenTests.test_enumrepresentationBadFormatc                 C  :   |   }t|t t|dd | | j d dS )z
        L{printFingerprint} writes a line to standard out giving the number of
        bits of the key, its fingerprint, and the basename of the file from it
        was read.
        r[   rH   rZ   z:2048 85:25:04:32:58:55:96:9f:57:ee:fb:a8:1a:ea:69:da temp
Nr>   r   
setContentr
   r   rC   r,   getvaluerW   r$   r$   r%   test_printFingerprint   s   z!KeyGenTests.test_printFingerprintc                 C  ri   )z
        L{printFigerprint} will print key fingerprint in
        L{FingerprintFormats.SHA256-BASE64} format if explicitly specified.
        ra   rj   z72048 FBTCOoknq0mHy+kpfnY9tDdcAJuWtCpuQMaV3EsvbUI= temp
Nrk   rW   r$   r$   r%   test_printFingerprintsha256   s   z'KeyGenTests.test_printFingerprintsha256c                 C  sf   |   }t|t | t}t|dd W d   n1 s"w   Y  | d|jj	d  dS )zx
        L{printFigerprint} raises C{keys.BadFingerprintFormat} when unsupported
        formats are requested.
        rd   rj   Nre   r   )
r>   r   rl   r
   rT   r   r   rC   rf   rI   )r0   rH   rg   r$   r$   r%   )test_printFingerprintBadFingerPrintFormat   s   z5KeyGenTests.test_printFingerprintBadFingerPrintFormatc                 C  s>   |   }t|d t t|dd | | j d dS )zn
        L{printFingerprint} checks if the filename with the  '.pub' suffix
        exists in ~/.ssh.
        r9   r[   rj   z>2048 85:25:04:32:58:55:96:9f:57:ee:fb:a8:1a:ea:69:da temp.pub
Nrk   rW   r$   r$   r%   #test_printFingerprintSuffixAppended   s   z/KeyGenTests.test_printFingerprintSuffixAppendedc                 C     t |  }|  |dj}tt}t||ddd | 	| j
 d||f  | 	||d dd| | 	t|d |  dS )z
        L{_saveKey} writes the private and public parts of a key to two
        different files and writes a report of this to standard out.
        id_rsa
passphraser[   rH   passrZ   Your identification has been saved in %s
Your public key has been saved in %s.pub
The key fingerprint in <FingerprintFormats=MD5_HEX> is:
85:25:04:32:58:55:96:9f:57:ee:fb:a8:1a:ea:69:da
N
id_rsa.pubr   r>   makedirschildpathr   
fromStringr   r   rC   r,   rm   
getContentpublicr0   baserH   keyr$   r$   r%   test_saveKey   s"   
zKeyGenTests.test_saveKeyc                 C  rr   )z
        L{_saveKey} writes the private and public parts of a key to two
        different files and writes a report of this to standard out.
        Test with ECDSA key.
        id_ecdsart   r[   ru   zYour identification has been saved in %s
Your public key has been saved in %s.pub
The key fingerprint in <FingerprintFormats=MD5_HEX> is:
1e:ab:83:a6:f2:04:22:99:7c:64:14:d2:ab:fa:f5:16
Nzid_ecdsa.pub)r   r>   rz   r{   r|   r   r}   r   r   rC   r,   rm   r~   r   r   r$   r$   r%   test_saveKeyECDSA   s"   
zKeyGenTests.test_saveKeyECDSAc                 C  rr   )z
        L{_saveKey} writes the private and public parts of a key to two
        different files and writes a report of this to standard out.
        Test with Ed25519 key.
        
id_ed25519rt   r[   ru   zYour identification has been saved in %s
Your public key has been saved in %s.pub
The key fingerprint in <FingerprintFormats=MD5_HEX> is:
ab:ee:c8:ed:e5:01:1b:45:b7:8d:b2:f0:8f:61:1c:14
Nzid_ed25519.pub)r   r>   rz   r{   r|   r   r}   r   r   rC   r,   rm   r~   r   r   r$   r$   r%   test_saveKeyEd25519   s$   
zKeyGenTests.test_saveKeyEd25519c                 C  rr   )z
        L{_saveKey} will generate key fingerprint in
        L{FingerprintFormats.SHA256-BASE64} format if explicitly specified.
        rs   rt   ra   ru   zYour identification has been saved in %s
Your public key has been saved in %s.pub
The key fingerprint in <FingerprintFormats=SHA256_BASE64> is:
FBTCOoknq0mHy+kpfnY9tDdcAJuWtCpuQMaV3EsvbUI=
Nrx   ry   r   r$   r$   r%   test_saveKeysha256  s&   
zKeyGenTests.test_saveKeysha256c                 C  s~   t |  }|  |dj}tt}| t	}t
||ddd W d   n1 s.w   Y  | d|jjd  dS )zq
        L{_saveKey} raises C{keys.BadFingerprintFormat} when unsupported
        formats are requested.
        rs   rt   rd   ru   Nre   r   )r   r>   rz   r{   r|   r   r}   r   rT   r   r   rC   rf   rI   )r0   r   rH   r   rg   r$   r$   r%    test_saveKeyBadFingerPrintformat,  s   

z,KeyGenTests.test_saveKeyBadFingerPrintformatc                 C  s`   t |  }|  |dj}tt}t||ddd | 	||d
 dd| dS )q
        L{_saveKey} will choose an empty string for the passphrase if
        no-passphrase is C{True}.
        rs   Tr[   rH   zno-passphraserZ   N    )r   r>   rz   r{   r|   r   r}   r   r   rC   r~   r   r$   r$   r%   test_saveKeyEmptyPassphrase>  s   
z'KeyGenTests.test_saveKeyEmptyPassphrasec                 C  ^   t |  }|  |dj}tt}t||ddd | 	||d
 d| dS )r   r   Tr[   r   N)r   r>   rz   r{   r|   r   r}   r   r   rC   r~   r   r$   r$   r%    test_saveKeyECDSAEmptyPassphraseN  s   
"z,KeyGenTests.test_saveKeyECDSAEmptyPassphrasec                 C  r   )r   r   Tr[   r   N)r   r>   rz   r{   r|   r   r}   r   r   rC   r~   r   r$   r$   r%   "test_saveKeyEd25519EmptyPassphrase\  s   
z.KeyGenTests.test_saveKeyEd25519EmptyPassphrasec                   s   t |  }|  |djg  ddl}d fdd	}| |jjj	d
fdd t
t}t|dddd| |d }||dd}| || dS )zd
        When no path is specified, it will ask for the path used to store the
        key.
        
custom_keyr   NrI   r   r   r   c                         d dS N appendrI   input_promptsr$   r%   
mock_inputx     
z6KeyGenTests.test_saveKeyNoFilename.<locals>.mock_input_inputSaveFilec                   s    S r   r$   r!   )keyPathr$   r%   <lambda>|      z4KeyGenTests.test_saveKeyNoFilename.<locals>.<lambda>Tr[   r   r   rI   r   r   r   )r   r>   rz   r{   r|   twisted.conch.scripts.ckeygenr-   conchscriptsr6   r   r}   r   r   r~   rC   )r0   r   twistedr   r   persistedKeyContentpersistedKeyr$   )r   r   r%   test_saveKeyNoFilenamel  s    

z"KeyGenTests.test_saveKeyNoFilenamec                 C  sj   ddd}t |  }|  |dj}| tjdd	d
  tt	}|ddd}| 
tt||| dS )zs
        When the specified file exists, it will ask the user for confirmation
        before overwriting.
        rI   r   r   	list[str]c                  W  s   dgS )Nnr$   r   r$   r$   r%   r     s   z6KeyGenTests.test_saveKeyFileExists.<locals>.mock_inputr   existsc                 S     dS )NTr$   r!   r$   r$   r%   r     r   z4KeyGenTests.test_saveKeyFileExists.<locals>.<lambda>Tr[   r   N)rI   r   r   r   )r   r>   rz   r{   r|   r-   osr   r}   r   rT   
SystemExitr   )r0   r   r   r   r   r_   r$   r$   r%   test_saveKeyFileExists  s   

z"KeyGenTests.test_saveKeyFileExistsc                 C  s   t |  }|  |dj}tt}t||dddd | 	| j
 d||f  |d }| 	||dd| | |d | 	t|d	 |  dS )
zi
        L{_saveKey} can be told to write the new private key file in OpenSSH
        v1 format.
        rs   rt   r[   rN   )rH   rv   rZ   private-key-subtyperw   N$   -----BEGIN OPENSSH PRIVATE KEY-----
rx   )r   r>   rz   r{   r|   r   r}   r   r   rC   r,   rm   r~   rF   
startswithr   )r0   r   rH   r   privateKeyContentr$   r$   r%   test_saveKeySubtypeV1  s4   
	z!KeyGenTests.test_saveKeySubtypeV1c                 C  sX   |   }tt}t|t td|i | j	 
dd}| ||d dS )zl
        L{displayPublicKey} prints out the public key associated with a given
        private key.
        rH   
asciiopensshN)r>   r   r}   r
   r   rl   r   r   r,   rm   stripencoderC   toStringr0   rH   rK   	displayedr$   r$   r%   test_displayPublicKey  s   
z!KeyGenTests.test_displayPublicKeyc                 C  sZ   |   }tt}t|t t|dd | j	 
dd}| ||d dS )z
        L{displayPublicKey} prints out the public key associated with a given
        private key using the given passphrase when it's encrypted.
        	encryptedrH   rv   r   r   r   N)r>   r   r}   r
   r   rl   r	   r   r,   rm   r   r   rC   r   r   r$   r$   r%   test_displayPublicKeyEncrypted  s   
z*KeyGenTests.test_displayPublicKeyEncryptedc                 C  sj   |   }tt}t|t | tddd  t	d|i | j
 dd}| ||d dS )	z
        L{displayPublicKey} prints out the public key associated with a given
        private key, asking for the passphrase when it's encrypted.
        getpassc                 S  r   )Nr   r$   )xr$   r$   r%   r     r   zLKeyGenTests.test_displayPublicKeyEncryptedPassphrasePrompt.<locals>.<lambda>rH   r   r   r   N)r>   r   r}   r
   r   rl   r	   r-   r   r   r,   rm   r   r   rC   r   r   r$   r$   r%   .test_displayPublicKeyEncryptedPassphrasePrompt  s   
z:KeyGenTests.test_displayPublicKeyEncryptedPassphrasePromptc                 C  s.   |   }t|t | tt|dd dS )z
        L{displayPublicKey} fails with a L{BadKeyError} when trying to decrypt
        an encrypted key with the wrong password.
        wrongr   N)r>   r   rl   r	   rT   r   r   rW   r$   r$   r%   $test_displayPublicKeyWrongPassphrase  s
   z0KeyGenTests.test_displayPublicKeyWrongPassphrasec                 C  sl   t ddd}| td| |  }t|t td|i | | j	
 dd | tt|  dS )zt
        L{changePassPhrase} allows a user to change the passphrase of a
        private key interactively.
        r   newpassr   rH   r   ;Your identification has been saved with the new passphrase.Nr)   r-   r   r>   r   rl   r	   r   rC   r,   rm   r   assertNotEqualr~   )r0   oldNewConfirmrH   r$   r$   r%   test_changePassphrase  s   z!KeyGenTests.test_changePassphrasec                 C  sl   t dd}| td| |  }t|t t|dd | | j	
 dd | tt|  dS )z
        L{changePassPhrase} allows a user to change the passphrase of a
        private key, providing the old passphrase and prompting for new one.
        r   r   r   r   r   r   Nr   )r0   
newConfirmrH   r$   r$   r%   test_changePassphraseWithOld   s   
z(KeyGenTests.test_changePassphraseWithOldc                 C  sV   |   }t|t t|ddd | | j dd | 	tt|
  dS )z
        L{changePassPhrase} allows a user to change the passphrase of a private
        key by providing both old and new passphrases without prompting.
        r   
newencrypt)rH   rv   r   r   r   N)r>   r   rl   r	   r   rC   r,   rm   r   r   r~   rW   r$   r$   r%   test_changePassphraseWithBoth  s   
z)KeyGenTests.test_changePassphraseWithBothc                 C  R   |   }t|t | tt|dd}| dt| | tt|	  dS )z
        L{changePassPhrase} exits if passed an invalid old passphrase when
        trying to change the passphrase of a private key.
        r   r   z1Could not change passphrase: old passphrase errorN)
r>   r   rl   r	   rT   r   r   rC   r   r~   r0   rH   errorr$   r$   r%   $test_changePassphraseWrongPassphrase'  s   z0KeyGenTests.test_changePassphraseWrongPassphrasec                 C  sb   |  tdtd |  }t|t | tt	d|i}| 
dt| | 
tt|  dS )z
        L{changePassPhrase} exits if no passphrase is specified for the
        C{getpass} call and the key is encrypted.
        r   r   rH   zMCould not change passphrase: Passphrase must be provided for an encrypted keyN)r-   r   r)   r>   r   rl   r	   rT   r   r   rC   r   r~   r   r$   r$   r%   !test_changePassphraseEmptyGetPass6  s   z-KeyGenTests.test_changePassphraseEmptyGetPassc                 C  sT   |   }t|d | ttd|i}d}| |t| | dt|  dS )zc
        L{changePassPhrase} exits if the file specified points to an invalid
        key.
        s   foobarrH   z?Could not change passphrase: cannot guess the type of b'foobar'N)	r>   r   rl   rT   r   r   rC   r   r~   )r0   rH   r   expectedr$   r$   r%   test_changePassphraseBadKeyF  s   z'KeyGenTests.test_changePassphraseBadKeyc                 C  sj   |   }t|t ddd}| td| | tt|d	d
}| 	dt
| | 	tt|  dS )z
        L{changePassPhrase} doesn't modify the key file if an unexpected error
        happens when trying to create the key with the new passphrase.
        rI   r   kwargsr   r   c                  _  s   t d)Noops)RuntimeErrorrI   r   r$   r$   r%   r   [  r'   z>KeyGenTests.test_changePassphraseCreateError.<locals>.toStringr   r   rH   r   z!Could not change passphrase: oopsN)rI   r   r   r   r   r   r>   r   rl   r   r-   r   rT   r   r   rC   r   r~   )r0   rH   r   r   r$   r$   r%    test_changePassphraseCreateErrorS  s   
z,KeyGenTests.test_changePassphraseCreateErrorc                 C  sn   |   }t|t ddd}| td| | tt|d	d
}d}| 	|t
| | 	tt|  dS )zq
        L{changePassPhrase} doesn't modify the key file if C{toString} returns
        an empty string.
        rI   r   r   r   r   c                  _  r   r   r$   r   r$   r$   r%   r   r  s   zCKeyGenTests.test_changePassphraseEmptyStringError.<locals>.toStringr   r   r   z9Could not change passphrase: cannot guess the type of b''N)rI   r   r   r   r   r   r   )r0   rH   r   r   r   r$   r$   r%   %test_changePassphraseEmptyStringErrorj  s   
z1KeyGenTests.test_changePassphraseEmptyStringErrorc                 C  r   )z
        L{changePassPhrase} exits when trying to change the passphrase on a
        public key, and doesn't change the file.
        rv   r   z.Could not change passphrase: key not encryptedN)
r>   r   rl   r
   rT   r   r   rC   r   r~   r   r$   r$   r%   test_changePassphrasePublicKey  s   z*KeyGenTests.test_changePassphrasePublicKeyc                 C  s   t ddd}| td| |  }t|t t|dd | | j	
 dd t| }| t| | |d d	S )
zq
        L{changePassPhrase} can be told to write the new private key file in
        OpenSSH v1 format.
        r   r   r   rN   )rH   r   r   r   r   N)r)   r-   r   r>   r   rl   r	   r   rC   r,   rm   r   r~   r   rF   r   )r0   r   rH   r   r$   r$   r%   test_changePassphraseSubtypeV1  s   z*KeyGenTests.test_changePassphraseSubtypeV1c                   sp   g  d fdd}ddi}t ||}| |d d | |tjd	d
 | dt  | dg  dS )zg
        L{options} will default to "~/.ssh/id_rsa" if the user doesn't
        specify a key.
        rI   r   r   r   c                    r   r   r   r   r   r$   r%   r     r   z5KeyGenTests.test_useDefaultForKey.<locals>.mock_inputrH   r   z.sshrs      Nr   )r   rC   rF   endswithr   r|   joinlen)r0   r   r_   rH   r$   r   r%   test_useDefaultForKey  s   
z!KeyGenTests.test_useDefaultForKeyc                 C  ,   ddi}|  tt|}| d|jd  dS )z
        Ensure FileNotFoundError is handled, whether the user has supplied
        a bad path, or has no key at the default path.
        rH   /foo/bar+could not be opened, please specify a file.r   N)rT   r   r   assertInrI   r0   r_   excr$   r$   r%   'test_displayPublicKeyHandleFileNotFound  s   z3KeyGenTests.test_displayPublicKeyHandleFileNotFoundc                 C  r   )N
        Ensure FileNotFoundError is handled for an invalid filename.
        rH   r   r   r   N)rT   r   r   r   rI   r   r$   r$   r%   'test_changePassPhraseHandleFileNotFound  s   z3KeyGenTests.test_changePassPhraseHandleFileNotFoundc                 C  s.   ddd}|  tt|}| d|jd  dS )r   r   r[   rj   r   r   N)rT   r   r   r   rI   r   r$   r$   r%   'test_printFingerprintHandleFileNotFound  s   
z3KeyGenTests.test_printFingerprintHandleFileNotFound)r   r+   )NN)r2   r   r3   r4   r5   r4   r   r+   ),__name__
__module____qualname____doc__r1   rL   rR   rX   r`   rc   rh   rn   ro   rp   rq   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r$   r$   r$   r%   r*   B   sX    























"















	r*   )r   r   r   r   )(r   
__future__r   r   r   r@   r.   ior   typingr   typing_extensionsr   twisted.conch.test.keydatar   r   r   r	   r
   twisted.python.filepathr   twisted.python.reflectr   twisted.trial.unittestr   r   r   r   r   r   r   r   twisted.conch.ssh.keysr   r   r   r   skipr)   r*   r$   r$   r$   r%   <module>   s&    
