
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
i                 @   s  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mZm	Z	 d dl
mZmZmZ d dlmZmZ d dlmZ e ZddlT ddlmZ dd	lmZ dd
lmZmZ ddlmZ ddlmZ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" ddl#m$Z$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/m0Z0m1Z1 dfZ2de"kZ3G dd deZ4G dd deZ5G dd deZ6G d d! d!eZ7G d"d# d#eZ8G d$d% d%eZ9G d&d' d'eZ:G d(d) d)eZ;G d*d+ d+eZ<G d,d- d-eZ=G d.d/ d/eZ>G d0d1 d1e>Z?G d2d3 d3eZ@G d4d5 d5eZAG d6d7 d7eZBG d8d9 d9ZCd:d; ZDd<d= ZEd>d? ZFd@dA ZGdBdC ZHdDdE ZIG dFdG dGZJG dHdI dIeJZKdJdK ZLG dLdM dMZMG dNdO dOZNG dPdQ dQeJZOG dRdS dSePZQG dTdU dUeNeOZRG dVdW dWeOZSG dXdY dYeNeSZTG dZd[ d[eNeSZUG d\d] d]eMeTZVG d^d_ d_eMeUZWG d`da daeUZXG dbdc dceXZYG ddde deeMeXZZeKeReTeUeYeVeWeZfZ[dS )g    N)
a2b_base64
b2a_base64hexlify)sha256sha512pbkdf2_hmac)HMACcompare_digest)create_logger   )*)
Compressor)
StableDict)ErrorIntegrityError)yes)get_keys_dirget_security_dir)get_limited_unpacker)
bin_to_hex)prepare_subprocess_env)msgpack)workarounds)KeyEncryptedKey)SaveFile   )NonceManager)AESbytes_to_longbytes_to_intnum_aes_blockshmac_sha256blake2b_256hkdf_hmac_sha512       Zauthenticated_no_keyc               @   s   e Zd ZdZdS )NoPassphraseFailurez can not acquire a passphrase: {}N)__name__
__module____qualname____doc__ r,   r,   /usr/lib64/python3.6/key.pyr'   &   s   r'   c               @   s   e Zd ZdZdS )PassphraseWrongzcpassphrase supplied in BORG_PASSPHRASE, by BORG_PASSCOMMAND or via BORG_PASSPHRASE_FD is incorrect.N)r(   r)   r*   r+   r,   r,   r,   r-   r.   *   s   r.   c               @   s   e Zd ZdZdS )PasscommandFailurez3passcommand supplied in BORG_PASSCOMMAND failed: {}N)r(   r)   r*   r+   r,   r,   r,   r-   r/   .   s   r/   c               @   s   e Zd ZdZdS )PasswordRetriesExceededz%exceeded the maximum password retriesN)r(   r)   r*   r+   r,   r,   r,   r-   r0   2   s   r0   c               @   s   e Zd ZdZdS )UnsupportedPayloadErrorzSUnsupported payload type {}. A newer version is required to access this repository.N)r(   r)   r*   r+   r,   r,   r,   r-   r1   6   s   r1   c               @   s   e Zd ZdZdS )UnsupportedManifestErrorzUUnsupported manifest envelope. A newer version is required to access this repository.N)r(   r)   r*   r+   r,   r,   r,   r-   r2   :   s   r2   c               @   s   e Zd ZdZdS )KeyfileNotFoundErrorz*No key file for repository {} found in {}.N)r(   r)   r*   r+   r,   r,   r,   r-   r3   >   s   r3   c               @   s   e Zd ZdZdS )KeyfileInvalidErrorz/Invalid key file for repository {} found in {}.N)r(   r)   r*   r+   r,   r,   r,   r-   r4   B   s   r4   c               @   s   e Zd ZdZdS )KeyfileMismatchErrorz/Mismatch between repository {} and key file {}.N)r(   r)   r*   r+   r,   r,   r,   r-   r5   F   s   r5   c               @   s   e Zd ZdZdS )RepoKeyNotFoundErrorz2No key entry found in the config of repository {}.N)r(   r)   r*   r+   r,   r,   r,   r-   r6   J   s   r6   c               @   s   e Zd Zejdj ZdZdS )TAMRequiredErroraT  
    Manifest is unauthenticated, but it is required for this repository.

    This either means that you are under attack, or that you modified this repository
    with a Borg version older than 1.0.9 after TAM authentication was enabled.

    In the latter case, use "borg upgrade --tam --force '{}'" to re-authenticate the manifest.
    FN)r(   r)   r*   textwrapdedentstripr+   	tracebackr,   r,   r,   r-   r7   N   s   
r7   c               @   s   e Zd Zejdj ZdZdS )ArchiveTAMRequiredErrorzR
    Archive '{}' is unauthenticated, but it is required for this repository.
    FN)r(   r)   r*   r8   r9   r:   r+   r;   r,   r,   r,   r-   r<   Z   s   
r<   c                   s&   e Zd ZejZdZ fddZ  ZS )
TAMInvalidFc                s   t  jd d S )Nz&Manifest authentication did not verify)super__init__)self)	__class__r,   r-   r?   e   s    zTAMInvalid.__init__)r(   r)   r*   r   r+   r;   r?   __classcell__r,   r,   )rA   r-   r=   a   s   r=   c                   s&   e Zd ZejZdZ fddZ  ZS )ArchiveTAMInvalidFc                s   t  jd d S )Nz%Archive authentication did not verify)r>   r?   )r@   )rA   r,   r-   r?   n   s    zArchiveTAMInvalid.__init__)r(   r)   r*   r   r+   r;   r?   rB   r,   r,   )rA   r-   rC   j   s   rC   c               @   s   e Zd ZdZdZdS )TAMUnsupportedSuiteErrorzMCould not verify manifest: Unsupported suite {!r}; a newer version is needed.FN)r(   r)   r*   r+   r;   r,   r,   r,   r-   rD   s   s   rD   c               @   s   e Zd ZdZdZdZdS )KeyBlobStorageZ
no_storagekeyfile
repositoryN)r(   r)   r*   
NO_STORAGEKEYFILEREPOr,   r,   r,   r-   rE   x   s   rE   c             C   sF   x@t D ]*}|j|jkr|jd k	s$t|j| |S qW td|j d S )NzInvalid encryption mode "%s")AVAILABLE_KEY_TYPESARG_NAMEZ
encryptionAssertionErrorcreate
ValueError)rG   argskeyr,   r,   r-   key_creator~   s
    
rR   c               C   s   dd t D S )Nc             S   s   g | ]}|j r|j qS r,   )rL   ).0rQ   r,   r,   r-   
<listcomp>   s    z&key_argument_names.<locals>.<listcomp>)rK   r,   r,   r,   r-   key_argument_names   s    rU   c             C   s>   | d }|t jkrtS x"tD ]}|j|kr|S qW t|d S )Nr   )PassphraseKeyTYPERepoKeyrK   r1   )manifest_dataZkey_typerQ   r,   r,   r-   identify_key   s    


rZ   c             C   s   t |j| |S )N)rZ   detect)rG   rY   r,   r,   r-   key_factory   s    r\   c             C   s   t t| j}tjj|dS )Ntam_required)r   r   idospathjoin)rG   Zsecurity_dirr,   r,   r-   tam_required_file   s    rb   c             C   s   t | }tjj|S )N)rb   r_   r`   isfile)rG   filer,   r,   r-   r]      s    r]   c               @   sv   e Zd ZdZdZdZejZdZ	dZ
dd Zdd Zdd	 ZdddZdd Zdd ZdddZdddZdddZdS )KeyBaseNZ	UNDEFINEDFc             C   s8   t | jg| _|| _d | _td| _| jj| _d| _d S )NZlz4T)	bytesrW   TYPE_STRrG   targetr   
compressor
decompressr]   )r@   rG   r,   r,   r-   r?      s    

zKeyBase.__init__c             C   s   dS )z1Return HMAC hash using the "id" HMAC key
        Nr,   )r@   datar,   r,   r-   id_hash   s    zKeyBase.id_hashc             C   s   d S )Nr,   )r@   chunkr,   r,   r-   encrypt   s    zKeyBase.encryptTc             C   s   d S )Nr,   )r@   r^   rk   rj   r,   r,   r-   decrypt   s    zKeyBase.decryptc             C   s,   |r(| j |}t||s(tdt| d S )Nz Chunk %s: id verification failed)rl   r	   r   r   )r@   r^   rk   Zid_computedr,   r,   r-   	assert_id   s    

zKeyBase.assert_idc             C   s"   t | j| j | j |d| ddS )Ns   borg-metadata-authentication-@   )ZikmsaltinfoZoutput_length)r$   id_keyenc_keyenc_hmac_key)r@   rr   contextr,   r,   r-   _tam_key   s
    zKeyBase._tam_key   manifestc             C   sr   |d krt jd}t|}tdtd|d }|d< tj|dd}| j||}t||tj	 |d< tj|ddS )Nrq   HKDF_HMAC_SHA512)typehmacrr   tamsurrogateescape)Zunicode_errorsr|   )
r_   urandomr   rf   r   packbrx   r   r   digest)r@   Zmetadata_dictrw   rr   r}   Zpackedtam_keyr,   r,   r-   pack_and_authenticate_metadata   s    
z&KeyBase.pack_and_authenticate_metadatac             C   s~  |j drt | j}|r,|r,tjd d}t|}td}|j| |j }t	rZ|dfS d|kr|rxt
| jjj ntjd |dfS |jdd	}t|tst |jd
djdd}|dkr|rtt|ntjd| |dfS |jd}|jd}	t|	t st|t rt |j|}
td||
|
d < | j|	dd}t||tj }t||slt tjd |dfS )z8Unpack msgpacked *data* and return (object, did_verify).      z!Manifest authentication DISABLED.FZmanifestTs   tamz'Manifest TAM not found and not requiredNs   types   <none>asciireplacerz   zPIgnoring manifest TAM made with unsupported suite, since TAM is not required: %rs   hmacs   saltrq   s   manifest)rw   zTAM-verified manifests   )
startswithr2   r]   loggerwarning	bytearrayr   feedunpackAUTHENTICATED_NO_KEYr7   rG   	_locationcanonical_pathdebugpop
isinstancedictr=   getdecoderD   reprrf   indexrx   r   r   r   r	   )r@   rk   force_tam_not_requiredr]   unpackerunpackedr}   tam_typetam_hmactam_saltoffsetr   calculated_hmacr,   r,   r-   unpack_and_verify_manifest   sL    








z"KeyBase.unpack_and_verify_manifestc             C   s  | j }|r|rtjd d}t|}td}|j| |j }d|kr||rh|jddjdd}t	|ntjd	 |dd
fS |j
dd
}t|tst |jddjdd}|dkr|rtt|ntjd| |dd
fS |jd}	|jd}
t|
t st|	t rt |j|	}td|||d < | j|
dd}t||tj }t||	s~dtkrxtjd |dd
fS t tjd |d|
fS )z>Unpack msgpacked *data* and return (object, did_verify, salt).z Archive authentication DISABLED.Farchives   tams   names	   <unknown>r   r   z&Archive TAM not found and not requiredNs   types   <none>rz   zOIgnoring archive TAM made with unsupported suite, since TAM is not required: %rs   hmacs   saltrq   s   archive)rw   Zignore_invalid_archive_tamz4ignoring invalid archive TAM due to BORG_WORKAROUNDSzTAM-verified archiveT)r]   r   r   r   r   r   r   r   r   r<   r   r   r   rC   rD   r   rf   r   rx   r   r   r   r	   r   )r@   rk   r   r]   r   r   Zarchive_namer}   r   r   r   r   r   r   r,   r,   r-   unpack_and_verify_archive  sL    













z!KeyBase.unpack_and_verify_archive)T)ry   N)F)F)r(   r)   r*   rW   NAMErL   rE   rH   STORAGE
chunk_seedlogically_encryptedr?   rl   rn   ro   rp   rx   r   r   r   r,   r,   r,   r-   re      s   	



,re   c                   sp   e Zd ZdZdZdZejZdZ	dZ
 fddZedd	 Zed
d Zdd Zdd ZdddZdd Z  ZS )PlaintextKeyr   Z	plaintextZnoner   Fc                s   t  j| d| _d S )NF)r>   r?   r]   )r@   rG   )rA   r,   r-   r?   U  s    zPlaintextKey.__init__c             C   s   t jd | |S )NzTEncryption NOT enabled.
Use the "--encryption=repokey|keyfile" to enable encryption.)r   rs   )clsrG   rP   r,   r,   r-   rN   Y  s    
zPlaintextKey.createc             C   s   | |S )Nr,   )r   rG   rY   r,   r,   r-   r[   ^  s    zPlaintextKey.detectc             C   s   t |j S )N)r   r   )r@   rk   r,   r,   r-   rl   b  s    zPlaintextKey.id_hashc             C   s   | j j|}dj| j|gS )N    )ri   compressra   rg   )r@   rm   rk   r,   r,   r-   rn   e  s    zPlaintextKey.encryptTc             C   s`   |d | j kr.|d k	rt|nd}td| t|dd  }|sF|S | j|}| j|| |S )Nr   z	(unknown)z%Chunk %s: Invalid encryption enveloper   )rW   r   r   
memoryviewrj   rp   )r@   r^   rk   rj   id_strpayloadr,   r,   r-   ro   i  s    
zPlaintextKey.decryptc             C   s   || S )Nr,   )r@   rr   rw   r,   r,   r-   rx   t  s    zPlaintextKey._tam_key)T)r(   r)   r*   rW   r   rL   rE   rH   r   r   r   r?   classmethodrN   r[   rl   rn   ro   rx   rB   r,   r,   )rA   r-   r   L  s   
r   c               C   s   t jdtd S )Nrq   )r_   r   rf   r,   r,   r,   r-   random_blake2b_256_keyx  s    r   c                   s*   e Zd ZdZdd Zd fdd	Z  ZS )ID_BLAKE2b_256zi
    Key mix-in class for using BLAKE2b-256 for the id key.

    The id_key length must be 32 bytes.
    c             C   s   t | j|S )N)r#   rt   )r@   rk   r,   r,   r-   rl     s    zID_BLAKE2b_256.id_hashNc                s*   |d kst t j  t | _t | _d S )N)rM   r>   init_from_random_datar   rv   rt   )r@   rk   )rA   r,   r-   r     s    
z$ID_BLAKE2b_256.init_from_random_data)N)r(   r)   r*   r+   rl   r   rB   r,   r,   )rA   r-   r     s   r   c               @   s   e Zd ZdZdd ZdS )ID_HMAC_SHA_256zj
    Key mix-in class for using HMAC-SHA-256 for the id key.

    The id_key length must be 32 bytes.
    c             C   s   t | j|S )N)r"   rt   )r@   rk   r,   r,   r-   rl     s    zID_HMAC_SHA_256.id_hashN)r(   r)   r*   r+   rl   r,   r,   r,   r-   r     s   r   c               @   sJ   e Zd ZdZdZeZdZdd Zddd	Z	d
d Z
dddZdddZdS )
AESKeyBasea  
    Common base class shared by KeyfileKey and PassphraseKey

    Chunks are encrypted using 256bit AES in Counter Mode (CTR)

    Payload layout: TYPE(1) + HMAC(32) + NONCE(8) + CIPHERTEXT

    To reduce payload size only 8 bytes of the 16 bytes nonce is saved
    in the payload, the first 8 bytes are always zeros. This does not
    affect security but limits the maximum repository capacity to
    only 295 exabytes!
    r       r&   Tc             C   s   | j j|}| jjtt| | jj  dj| jj	dd  | jj
|f}| jtkrdt| jdks| jtkr|t| jdkst| j| j|}dj| j||fS )Nr   r&      r   )ri   r   nonce_managerZensure_reservationr!   len
enc_cipherresetra   ivrn   MACr#   rv   r"   rM   rg   )r@   rm   rk   r|   r,   r,   r-   rn     s    
"zAESKeyBase.encryptc       	      C   s$  |d | j kp$|d tj ko$t| tsF|d k	r6t|nd}td| t|}|dd }| jtkrrt	| j
dks| jtkrt	| j
dkstt| j| j
|dd  }t||s|d k	rt|nd}td| | jjt|dd	  d
 | jj|d	d  }|s
|S | j|}| j|| |S )Nr   z	(unknown)z%Chunk %s: Invalid encryption enveloper   !   r   r   z/Chunk %s: Encryption envelope checksum mismatch)   )r   )rW   rV   r   rX   r   r   r   r   r#   r   rv   r"   rM   r	   
dec_cipherr   PREFIXro   rj   rp   )	r@   r^   rk   rj   r   Z	data_viewZ
hmac_givenZhmac_computedr   r,   r,   r-   ro     s&    

zAESKeyBase.decryptc             C   sB   |d | j kp$|d tj ko$t| ts.tdt|dd }|S )Nr   z%Manifest: Invalid encryption enveloper   r   )rW   rV   r   rX   r   r   )r@   r   Znoncer,   r,   r-   extract_nonce  s
    zAESKeyBase.extract_nonceNc             C   sl   |d krt jd}|dd | _|dd | _|dd | _t|dd | _| jd@ rh| jd d | _d S )	Nd   r   r   rq   `   l        l    r   )r_   r   ru   rv   rt   r    r   )r@   rk   r,   r,   r-   r     s    

z AESKeyBase.init_from_random_datar   c             C   sB   t d| j|jdddd| _t| j| j|| _t d| jd| _d S )NT   Zbig)	byteorder)
is_encryptrQ   r   F)r   rQ   )r   ru   to_bytesr   r   rG   r   r   )r@   Zmanifest_noncer,   r,   r-   init_ciphers  s    zAESKeyBase.init_ciphersr   r   )T)N)r   )r(   r)   r*   r+   ZPAYLOAD_OVERHEADr"   r   r   rn   ro   r   r   r   r,   r,   r,   r-   r     s   


r   c               @   s   e Zd ZedddZedddZedddZedd	 Zedd
dZedd Z	edd Z
edddZdd Zdd ZdS )
PassphraseNc             C   s"   t jj||}|d k	r| |S d S )N)r_   environr   )r   env_vardefault
passphraser,   r,   r-   _env_passphrase  s    zPassphrase._env_passphrasec             C   sD   | j d|}|d k	r|S | j }|d k	r,|S | j }|d k	r@|S d S )NBORG_PASSPHRASE)r   env_passcommandfd_passphrase)r   r   r   r,   r,   r-   env_passphrase  s    zPassphrase.env_passphrasec             C   s~   t jjdd }|d k	rztdd}ytjtj|d|d}W n0 tjt	fk
rj } zt
|W Y d d }~X nX | |jdS d S )NBORG_PASSCOMMANDT)system)Zuniversal_newlinesenv
)r_   r   r   r   
subprocessZcheck_outputshlexsplitZCalledProcessErrorFileNotFoundErrorr/   rstrip)r   r   Zpasscommandr   r   er,   r,   r-   r      s    
zPassphrase.env_passcommandc             C   s^   yt tjjd}W n ttfk
r,   d S X tj|dd}|j }W d Q R X | |jdS )NZBORG_PASSPHRASE_FDr)moder   )	intr_   r   r   rO   	TypeErrorfdopenreadr   )r   fdfr   r,   r,   r-   r     s    zPassphrase.fd_passphrasec             C   s   | j d|S )NZBORG_NEW_PASSPHRASE)r   )r   r   r,   r,   r-   env_new_passphrase  s    zPassphrase.env_new_passphrasec             C   s   yt j |}W nt tk
r   |r(t  g }x6dD ].}tjj|d k	}|jd||rVdndf  q2W |jd tdj|d Y n
X | |S d S )	Nr   r   z	%s is %s.setznot setz"Interactive password query failed. )r   r   )	getpassEOFErrorprintr_   r   r   appendr'   ra   )r   promptZpwmsgr   Zenv_var_setr,   r,   r-   r     s    

zPassphrase.getpassc             C   s   d}t ||ddddrtd| tjd tdtjd y|jd	 W n> tk
r   td
t|jd tjd tdtjd Y nX d S )NzDDo you want your passphrase to be displayed for verification? [yN]: zInvalid answer, try again.TZBORG_DISPLAY_PASSPHRASE)Z	retry_msgZinvalid_msgretryZenv_var_overridez-Your passphrase (between double-quotes): "%s")rd   zDMake sure the passphrase displayed above is exactly what you wanted.r   z+Your passphrase (UTF-8 encoding in hex): %szutf-8zAs you have a non-ASCII passphrase, it is recommended to keep the UTF-8 encoding in hex together with the passphrase at a safe place.)r   r   sysstderrencodeUnicodeEncodeErrorr   )r   r   r   r,   r,   r-   verification*  s    



zPassphrase.verificationFc             C   s   | j  }|d k	r|S | j }|d k	r(|S xptddD ]^}| jd}|sJ|r| jd}||krt| j| tjd |S tdtj	d q4tdtj	d q4W t
d S )	Nr      zEnter new passphrase: zEnter same passphrase again: zDRemember your passphrase. Your data will be inaccessible without it.zPassphrases do not match)rd   zPassphrase must not be blank)r   r   ranger   r   r   rs   r   r   r   r0   )r   allow_emptyr   r   Zpassphrase2r,   r,   r-   new<  s"    



zPassphrase.newc             C   s   dS )Nz<Passphrase "***hidden***">r,   )r@   r,   r,   r-   __repr__S  s    zPassphrase.__repr__c             C   s   t d| jd|||S )Nr   zutf-8)r   r   )r@   rr   
iterationsZlengthr,   r,   r-   kdfV  s    zPassphrase.kdf)N)N)N)N)F)r(   r)   r*   r   r   r   r   r   r   r   r   r   r   r   r,   r,   r,   r-   r     s   
r   c               @   sJ   e Zd ZdZdZdZejZdZ	e
dd Ze
dd Zd	d
 Zdd ZdS )rV   r   r   Ni c             C   s.   | |}t jd tjdd}|j|| |S )Nz9WARNING: "passphrase" mode is unsupported since borg 1.0.F)r   )r   r   r   r   init)r   rG   rP   rQ   r   r,   r,   r-   rN   j  s
    
zPassphraseKey.createc             C   s   d|j j  }| |}tj }|d kr0tj|}x|tddD ]j}|j|| y:|jd | tt	|d }|j
|j||  ||_|S  tk
r   tj|}Y q<X q<W td S )NzEnter passphrase for %s: r      r   )r   r   r   r   r   r   r   ro   r!   r   r   r   _passphraser   r0   )r   rG   rY   r   rQ   r   r   
num_blocksr,   r,   r-   r[   r  s     
zPassphraseKey.detectc             C   s   G dd dt }|d S )Nc               @   s   e Zd ZdZdS )zAPassphraseKey.change_passphrase.<locals>.ImmutablePassphraseErrorz=The passphrase for this encryption key type can't be changed.N)r(   r)   r*   r+   r,   r,   r,   r-   ImmutablePassphraseError  s   r   )r   )r@   r   r,   r,   r-   change_passphrase  s    zPassphraseKey.change_passphrasec             C   s*   | j |j|j| jd | j  d| _d S )Nr   F)r   r   r^   r   r   r]   )r@   rG   r   r,   r,   r-   r     s    zPassphraseKey.init)r(   r)   r*   rW   r   rL   rE   rH   r   r   r   rN   r[   r   r   r,   r,   r,   r-   rV   Z  s   	rV   c               @   sp   e Zd Zedd Zdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dddZedd ZdddZdd ZdS )KeyfileKeyBasec       	      C   s   | |}|j  }d| }tj }|d krlt }|j||s|x@tddD ]}tj|}|j||rFP qFW tn|j||s|ttt	|d }|j
|j||  ||_|S )NzEnter passphrase for key %s: r   r   r   )find_keyr   r   loadr   r   r0   r.   r!   r   r   r   r   )	r   rG   rY   rQ   rh   r   r   r   r   r,   r,   r-   r[     s$    
zKeyfileKeyBase.detectc             C   s   t d S )N)NotImplementedError)r@   r,   r,   r-   r    s    zKeyfileKeyBase.find_keyc             C   s   t d S )N)r  )r@   rh   r   r,   r,   r-   r    s    zKeyfileKeyBase.loadc             C   s   t |}| j||}|r~tj|}t|d}|jdkr>td|j| _|j| _|j	| _	|j
| _
|j| _|jdt| j| _dS dS )N)internal_dictr   z5key version %d is not supported by this borg version.r]   TF)r   decrypt_key_filer   Zunpackbr   versionr   repository_idru   rv   rt   r   r   r]   rG   )r@   key_datar   cdatark   rQ   r,   r,   r-   _load  s    


zKeyfileKeyBase._loadc             C   s   t d}|j| |j }t|d}|jdkr<td|j |jdkrTtd|j |j|j|j	d}t
d|d	j|j}tt|||jr|S d S )
NrQ   )r  r   z?encrypted key version %d is not supported by this borg version.r   zCencrypted key algorithm '%s' is not supported by this borg version.r   F)r   rQ   )r   r   r   r   r  r   	algorithmr   rr   r   r   ro   rk   r	   r"   hash)r@   rk   r   r   ru   rQ   r,   r,   r-   r    s    



zKeyfileKeyBase.decrypt_key_filec       	      C   sZ   t jd}t}|j||d}t||}td|dj|}td||d||d}tj	|j
 S )Nr   T)r   rQ   r   r   )r  rr   r   r  r  rk   )r_   r   ZPBKDF2_ITERATIONSr   r"   r   rn   r   r   r   as_dict)	r@   rk   r   rr   r   rQ   r  r
  ru   r,   r,   r-   encrypt_key_file  s    

zKeyfileKeyBase.encrypt_key_filec          	   C   sV   t d| j| j| j| j| j| jd}| jtj	|j
 |}djtjt|jd}|S )Nr   )r  r  ru   rv   rt   r   r]   r   r   )r   r  ru   rv   rt   r   r]   r  r   r   r  ra   r8   Zwrapr   r   )r@   r   rQ   rk   r	  r,   r,   r-   _save  s    
zKeyfileKeyBase._saveNc             C   s&   |d krt jdd}| j| j| d S )NT)r   )r   r   saverh   )r@   r   r,   r,   r-   r     s    z KeyfileKeyBase.change_passphrasec             C   sb   t jdd}| |}|j|_|j  |j  |j|}|j||dd tj	d|  tj	d |S )NT)r   )rN   zKey in "%s" created.z>Keep this key safe. Your data will be inaccessible without it.)
r   r   r^   r  r   r   get_new_targetr  r   rs   )r   rG   rP   r   rQ   rh   r,   r,   r-   rN     s    

zKeyfileKeyBase.createFc             C   s   t d S )N)r  )r@   rh   r   rN   r,   r,   r-   r    s    zKeyfileKeyBase.savec             C   s   t d S )N)r  )r@   rP   r,   r,   r-   r    s    zKeyfileKeyBase.get_new_target)N)F)r(   r)   r*   r   r[   r  r  r  r  r  r  r   rN   r  r  r,   r,   r,   r-   r    s   

r  c               @   sL   e Zd ZdZdZdZejZdZ	dd Z
dd Zd	d
 Zdd ZdddZdS )
KeyfileKeyr   zkey filerF   BORG_KEYc          
   C   sx   | j j d }t|}t|dN}|jt||krFt| jjj	 ||jt||krjt
| jjj	 ||S Q R X d S )N    rb)FILE_IDr   r   openr   r   r4   rG   r   r   r5   )r@   filenamer^   Zfile_idZrepo_idr   r,   r,   r-   sanity_check  s    zKeyfileKey.sanity_checkc             C   s   | j j}tjjd}|r,| jtjj||S t }xFtj	|D ]8}tjj
||}y| j||S  ttfk
rt   Y q>X q>W t| j jj t d S )NBORG_KEY_FILE)rG   r^   r_   r   r   r  r`   abspathr   listdirra   r4   r5   r3   r   r   )r@   r^   rF   Zkeys_dirnamer  r,   r,   r-   r    s    
zKeyfileKey.find_keyc             C   sX   t jjd}|rt jj|S |jj }|}d}x$t jj|rR|d7 }|d|  }q0W |S )Nr  r   z.%d)r_   r   r   r`   r  locationZto_key_filenameexists)r@   rP   rF   r  r`   ir,   r,   r-   r  (  s    
zKeyfileKey.get_new_targetc             C   sF   t |d}dj|j dd  }W d Q R X | j||}|rB|| _|S )Nr    r   )r  ra   	readlinesr  rh   )r@   rh   r   r   r	  successr,   r,   r-   r  4  s     zKeyfileKey.loadFc             C   sr   |rt jj|rtd| | j|}t|4}|jd| jt| j	f  |j| |jd W d Q R X || _
d S )Nz,Aborting because key in "%s" already exists.z%s %s
r   )r_   r`   rc   r   r  r   writer  r   r  rh   )r@   rh   r   rN   r	  r   r,   r,   r-   r  <  s    


zKeyfileKey.saveN)F)r(   r)   r*   rW   r   rL   rE   rI   r   r  r  r  r  r  r  r,   r,   r,   r-   r    s   r  c               @   s@   e Zd ZdZdZdZejZdd Z	dd Z
dd Zdd
dZdS )rX   r   Zrepokeyc             C   s(   | j jj }| j j }|s$t|d |S )N)rG   r   r   load_keyr6   )r@   locrQ   r,   r,   r-   r  P  s
    

zRepoKey.find_keyc             C   s   | j S )N)rG   )r@   rP   r,   r,   r-   r  X  s    zRepoKey.get_new_targetc             C   sT   |dk| _ | j}|j }|s0|jj }t|d |jd}| j||}|rP|| _|S )Nr"  zutf-8)	r   rG   r&  r   r   r6   r   r  rh   )r@   rh   r   r	  r'  r$  r,   r,   r-   r  [  s    



zRepoKey.loadFc             C   s2   |dk| _ | j|}|jd}|j| || _d S )Nr"  zutf-8)r   r  r   Zsave_keyrh   )r@   rh   r   rN   r	  r,   r,   r-   r  m  s
    



zRepoKey.saveN)F)r(   r)   r*   rW   r   rL   rE   rJ   r   r  r  r  r  r,   r,   r,   r-   rX   J  s   rX   c               @   s&   e Zd ZdZdZdZejZdZ	e
ZdS )Blake2KeyfileKeyr   zkey file BLAKE2bzkeyfile-blake2r  N)r(   r)   r*   rW   r   rL   rE   rI   r   r  r#   r   r,   r,   r,   r-   r(  u  s   r(  c               @   s"   e Zd ZdZdZdZejZe	Z
dS )Blake2RepoKey   zrepokey BLAKE2bzrepokey-blake2N)r(   r)   r*   rW   r   rL   rE   rJ   r   r#   r   r,   r,   r,   r-   r)    s
   r)  c                   sZ   e Zd ZejZdZ fddZ fddZd fdd	Z	dd	 Z
d
d ZdddZ  ZS )AuthenticatedKeyBaseFc                sB   t r4td}|| _|| _|| _|| _d| _d| _dS t j	||S )Nr   r   FT)
r   rf   r  ru   rv   rt   r   r]   r>   r  )r@   r	  r   ZNOPE)rA   r,   r-   r    s    zAuthenticatedKeyBase._loadc                s   t  j||}d| _|S )NF)r>   r  r   )r@   rh   r   r$  )rA   r,   r-   r    s    zAuthenticatedKeyBase.loadc                s   t  j|||d d| _d S )N)rN   F)r>   r  r   )r@   rh   r   rN   )rA   r,   r-   r    s    zAuthenticatedKeyBase.savec             C   s   |d | j krtddS )Nr   z%Manifest: Invalid encryption envelope*   )rW   r   )r@   r   r,   r,   r-   r     s    z"AuthenticatedKeyBase.extract_noncec             C   s   | j j|}dj| j|gS )Nr   )ri   r   ra   rg   )r@   rm   rk   r,   r,   r-   rn     s    zAuthenticatedKeyBase.encryptTc             C   sX   |d | j krtdt| t|dd  }|s6|S | j|}trH|S | j|| |S )Nr   zChunk %s: Invalid enveloper   )rW   r   r   r   rj   r   rp   )r@   r^   rk   rj   r   r,   r,   r-   ro     s    
zAuthenticatedKeyBase.decrypt)F)T)r(   r)   r*   rE   rJ   r   r   r  r  r  r   rn   ro   rB   r,   r,   )rA   r-   r+    s   r+  c               @   s   e Zd ZdZdZdZdS )AuthenticatedKey   ZauthenticatedN)r(   r)   r*   rW   r   rL   r,   r,   r,   r-   r-    s   r-  c               @   s   e Zd ZdZdZdZdS )Blake2AuthenticatedKey   zauthenticated BLAKE2bzauthenticated-blake2N)r(   r)   r*   rW   r   rL   r,   r,   r,   r-   r/    s   r/  s           )\r   r_   r   r   r8   r   Zbinasciir   r   r   Zhashlibr   r   r   r|   r   r	   Zborg.loggerr
   r   Z	constantsr   r   Zhelpersr   r   r   r   r   r   r   r   r   r   r   itemr   r   platformr   Znoncesr   Z	low_levelr   r   r    r!   r"   r#   r$   r   r   r'   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r<   r=   rC   rD   rE   rR   rU   rZ   r\   rb   r]   re   r   r   r   r   r   strr   rV   r  r  rX   r(  r)  r+  r-  r/  rK   r,   r,   r,   r-   <module>   s   $			 &,Km8tD+
	8