o
    +ke                     @   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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 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-m.Z.m/Z/m0Z0 ddl(m1Z1m2Z2 de v 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 d.d/ d/e>Z?G d0d1 d1eZ@G d2d3 d3eZAG d4d5 d5eZBG d6d7 d7ZCd8d9 ZDd:d; ZEd<d= ZFd>d? ZGd@dA ZHdBdC ZIG dDdE dEZJG dFdG dGeJZKdHdI ZLG dJdK dKZMG dLdM dMZNG dNdO dOeJZOG dPdQ dQePZQG dRdS dSeNeOZRG dTdU dUeOZSG dVdW dWeNeSZTG dXdY dYeNeSZUG dZd[ d[eMeTZVG d\d] d]eMeUZWG d^d_ d_eUZXG d`da daeXZYG dbdc dceMeXZZeKeReTeUeYeVeWeZfZ[dS )d    N)
a2b_base64
b2a_base64hexlify)sha256sha512pbkdf2_hmac   )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long_to_bytesbytes_to_intnum_cipher_blockshmac_sha256blake2b_256hkdf_hmac_sha512)AES256_CTR_HMAC_SHA256AES256_CTR_BLAKE2bZauthenticated_no_keyc                   @      e Zd ZdZdS )NoPassphraseFailurez can not acquire a passphrase: {}N__name__
__module____qualname____doc__ r-   r-   3usr/lib/python3.10/site-packages/borg/crypto/key.pyr'   (       r'   c                   @   r&   )PassphraseWrongzcpassphrase supplied in BORG_PASSPHRASE, by BORG_PASSCOMMAND or via BORG_PASSPHRASE_FD is incorrect.Nr(   r-   r-   r-   r.   r0   ,   r/   r0   c                   @   r&   )PasscommandFailurez3passcommand supplied in BORG_PASSCOMMAND failed: {}Nr(   r-   r-   r-   r.   r1   0   r/   r1   c                   @   r&   )PasswordRetriesExceededz%exceeded the maximum password retriesNr(   r-   r-   r-   r.   r2   4   r/   r2   c                   @   r&   )UnsupportedPayloadErrorzSUnsupported payload type {}. A newer version is required to access this repository.Nr(   r-   r-   r-   r.   r3   8   r/   r3   c                   @   r&   )UnsupportedManifestErrorzUUnsupported manifest envelope. A newer version is required to access this repository.Nr(   r-   r-   r-   r.   r4   <   r/   r4   c                   @   r&   )KeyfileNotFoundErrorz*No key file for repository {} found in {}.Nr(   r-   r-   r-   r.   r5   @   r/   r5   c                   @   r&   )KeyfileInvalidErrorz/Invalid key file for repository {} found in {}.Nr(   r-   r-   r-   r.   r6   D   r/   r6   c                   @   r&   )KeyfileMismatchErrorz/Mismatch between repository {} and key file {}.Nr(   r-   r-   r-   r.   r7   H   r/   r7   c                   @   r&   )RepoKeyNotFoundErrorz2No key entry found in the config of repository {}.Nr(   r-   r-   r-   r.   r8   L   r/   r8   c                   @      e Zd Zed 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.
    TNr)   r*   r+   textwrapdedentstripr,   	tracebackr-   r-   r-   r.   r:   P   s
    r:   c                   @   r9   )ArchiveTAMRequiredErrorzR
    Archive '{}' is unauthenticated, but it is required for this repository.
    TNr;   r-   r-   r-   r.   r@   \   s
    r@   c                       &   e Zd ZejZdZ fddZ  ZS )
TAMInvalidTc                       t  d d S )Nz&Manifest authentication did not verifysuper__init__self	__class__r-   r.   rF   g      zTAMInvalid.__init__r)   r*   r+   r   r,   r?   rF   __classcell__r-   r-   rI   r.   rB   c       rB   c                       rA   )ArchiveTAMInvalidTc                    rC   )Nz%Archive authentication did not verifyrD   rG   rI   r-   r.   rF   p   rK   zArchiveTAMInvalid.__init__rL   r-   r-   rI   r.   rO   l   rN   rO   c                   @   s   e Zd ZdZdZdS )TAMUnsupportedSuiteErrorzMCould not verify manifest: Unsupported suite {!r}; a newer version is needed.TN)r)   r*   r+   r,   r?   r-   r-   r-   r.   rP   u   s    rP   c                   @      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.   rR   z       rR   c                 C   sB   t D ]}|j|jkr|jd usJ || |  S qtd|j )NzInvalid encryption mode "%s")AVAILABLE_KEY_TYPESARG_NAMEZ
encryptioncreate
ValueError)rT   argskeyr-   r-   r.   key_creator   s   r_   c                   C   s   dd t D S )Nc                 S   s   g | ]}|j r|j qS r-   )rZ   ).0r^   r-   r-   r.   
<listcomp>   s    z&key_argument_names.<locals>.<listcomp>)rY   r-   r-   r-   r.   key_argument_names   s   rb   c                 C   s:   | d }|t jkrtS tD ]}|j|kr|  S qt|)Nr   )PassphraseKeyTYPERepoKeyrY   r3   )manifest_dataZkey_typer^   r-   r-   r.   identify_key   s   

rg   c                 C   s   t || |S N)rg   detect)rT   rf   r-   r-   r.   key_factory   s   rj   c                 C   s   t t| j}tj|dS )Ntam_required)r   r   idospathjoin)rT   Zsecurity_dirr-   r-   r.   tam_required_file   s   rp   c                 C   s   t | }tj|S rh   )rp   rm   rn   isfile)rT   filer-   r-   r.   rk      s   rk   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 )Nlz4T)	bytesrd   TYPE_STRrT   targetr   
compressor
decompressrk   rH   rT   r-   r-   r.   rF      s   


zKeyBase.__init__c                 C      dS )z1Return HMAC hash using the "id" HMAC key
        Nr-   rH   datar-   r-   r.   id_hash   s    zKeyBase.id_hashc                 C      d S rh   r-   )rH   chunkr-   r-   r.   encrypt      zKeyBase.encryptTc                 C   r   rh   r-   )rH   rl   r}   ry   r-   r-   r.   decrypt   r   zKeyBase.decryptc                 C   s2   |r|  |}t||stdt| d S d S )Nz Chunk %s: id verification failed)r~   hmaccompare_digestr   r   )rH   rl   r}   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rH   r   contextr-   r-   r.   _tam_key   s   zKeyBase._tam_key   manifestc                 C   sh   |d u r	t d}t|}tdtd|d }|d< t|}| ||}t||d|d< t|S )Nr   HKDF_HMAC_SHA512)typer   r   tamr   r   )	rm   urandomr   ru   r   packbr   r   digest)rH   Zmetadata_dictr   r   r   Zpackedtam_keyr-   r-   r.   pack_and_authenticate_metadata   s   


z&KeyBase.pack_and_authenticate_metadatac                 C   sp  | drt | j}|r|rtd d}t|}td}|| | }t	r-|dfS d|vrD|r;t
| jj td |dfS |dd}t|tsRt |d	d
dd}|dkrr|rhtt|td| |dfS |d}|d}	t|	trt|tst ||}
td||
|
d < | j|	dd}t||d}t||st td |dfS )z8Unpack msgpacked *data* and return (object, did_verify).s   z!Manifest authentication DISABLED.FmanifestT   tamz'Manifest TAM not found and not requiredN   type   <none>asciireplacer   zPIgnoring manifest TAM made with unsupported suite, since TAM is not required: %r   hmac   saltr   r   r   r   zTAM-verified manifest)
startswithr4   rk   loggerwarning	bytearrayr   feedunpackAUTHENTICATED_NO_KEYr:   rT   	_locationcanonical_pathdebugpop
isinstancedictrB   getdecoderP   reprru   indexr   r   r   r   )rH   r}   force_tam_not_requiredrk   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d d}t|}td}|| | }d|vr=|r3|dddd}t	|td	 |dd
fS |
dd
}t|tsKt |dddd}|dkrl|ratt|td| |dd
fS |d}	|d}
t|
trt|	tst ||	}td|||d < | j|
dd}t||d}t||	sdtv rtd |dd
fS t td |d|
fS )z>Unpack msgpacked *data* and return (object, did_verify, salt).z Archive authentication DISABLED.Farchiver   s   names	   <unknown>r   r   z&Archive TAM not found and not requiredNr   r   r   zOIgnoring archive TAM made with unsupported suite, since TAM is not required: %rr   r   r   s   archiver   r   Zignore_invalid_archive_tamz4ignoring invalid archive TAM due to BORG_WORKAROUNDSzTAM-verified archiveT)rk   r   r   r   r   r   r   r   r   r@   r   r   r   rO   rP   r   ru   r   r   r   r   r   r   )rH   r}   r   rk   r   r   archive_namer   r   r   r   r   r   r   r-   r-   r.   unpack_and_verify_archive  sL   












z!KeyBase.unpack_and_verify_archiveT)r   NF)r)   r*   r+   rd   NAMErZ   rR   rU   STORAGE
chunk_seedlogically_encryptedrF   r~   r   r   r   r   r   r   r   r-   r-   r-   r.   rs      s     	



,rs   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	plaintextnoner   Fc                    s   t  | d| _d S NF)rE   rF   rk   rz   rI   r-   r.   rF   W  s   
zPlaintextKey.__init__c                 C   s   t d | |S )NzTEncryption NOT enabled.
Use the "--encryption=repokey|keyfile" to enable encryption.)r   r   )clsrT   r]   r-   r-   r.   r[   [  s   
zPlaintextKey.createc                 C   s   | |S rh   r-   )r   rT   rf   r-   r-   r.   ri   `  s   zPlaintextKey.detectc                 C   s   t | S rh   )r   r   r|   r-   r-   r.   r~   d     zPlaintextKey.id_hashc                 C      | j |}d| j|gS N    rx   compressro   rv   rH   r   r}   r-   r-   r.   r   g     zPlaintextKey.encryptTc                 C   s`   |d | j kr|d urt|nd}td| t|dd  }|s#|S | |}| || |S )Nr   	(unknown)%Chunk %s: Invalid encryption enveloper   )rd   r   r   
memoryviewry   r   rH   rl   r}   ry   id_strpayloadr-   r-   r.   r   k  s   
zPlaintextKey.decryptc                 C   s   || S rh   r-   r   r-   r-   r.   r   v  s   zPlaintextKey._tam_keyr   )r)   r*   r+   rd   r   rZ   rR   rU   r   r   r   rF   classmethodr[   ri   r~   r   r   r   rM   r-   r-   rI   r.   r   N  s     


r   c                   C   s   t dtd S )Nr   )rm   r   ru   r-   r-   r-   r.   random_blake2b_256_keyz  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      t | j|S rh   )r"   r   r|   r-   r-   r.   r~     r   zID_BLAKE2b_256.id_hashNc                    s*   |d u sJ t    t | _t | _d S rh   )rE   init_from_random_datar   r   r   r|   rI   r-   r.   r     s   
z$ID_BLAKE2b_256.init_from_random_datarh   )r)   r*   r+   r,   r~   r   rM   r-   r-   rI   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   r   rh   )r!   r   r|   r-   r-   r.   r~     r   zID_HMAC_SHA_256.id_hashN)r)   r*   r+   r,   r~   r-   r-   r-   r.   r     s    r   c                   @   sB   e Zd ZdZdZeZdZdd Zd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!
    )   Tc                 C   s@   | j |}| j| j | jt|}| jj|| j	|dS )N)headerZiv)
rx   r   nonce_managerZensure_reservationciphernext_ivZblock_countlenr   rv   )rH   r   r}   r   r-   r-   r.   r     s
   zAESKeyBase.encryptc              
   C   s   |d | j ks#|d tj krt| ts#|d urt|nd}td| z| j|}W n tyF } ztdt| dt| dd }~ww |sK|S | 	|}| 
|| |S )Nr   r   r   zChunk z: Could not decrypt [])rd   rc   r   re   r   r   r   r   strry   r   )rH   rl   r}   ry   r   r   er-   r-   r.   r     s   
zAESKeyBase.decryptNc                 C   sp   |d u r	t d}|dd | _|dd | _|dd | _t|dd | _| jd@ r6| jd d | _d S d S )	Nd   r       r   `   l        l    r   )rm   r   r   r   r   r   r   r|   r-   r-   r.   r     s   

z AESKeyBase.init_from_random_datac                 C   s   | j | j| jddd| _|d u rd}n%|d | jks*|d tjkr&t| ts*tdt	t
|}| j|| }| j| t| j|| _d S )Nr   )Zmac_keyr   Z
header_lenZ
aad_offsetr   %Manifest: Invalid encryption envelope)CIPHERSUITEr   r   r   rd   rc   r   re   r   r    r   Z
extract_ivZset_ivr   rT   r   )rH   rf   ZnonceZmanifest_blocksr-   r-   r.   init_ciphers  s   zAESKeyBase.init_ciphersr   rh   )r)   r*   r+   r,   ZPAYLOAD_OVERHEADr$   r   r   r   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||}|d ur| |S d S rh   )rm   environr   )r   env_vardefault
passphraser-   r-   r.   _env_passphrase  s   zPassphrase._env_passphrasec                 C   sD   |  d|}|d ur|S |  }|d ur|S |  }|d u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   st   t jdd }|d ur8tdd}ztjt|d|d}W n tjt	fy0 } zt
|d }~ww | |dS d S )NBORG_PASSCOMMANDT)system)universal_newlinesenv
)rm   r   r   r   
subprocesscheck_outputshlexsplitCalledProcessErrorFileNotFoundErrorr1   rstrip)r   r   Zpasscommandr   r   r   r-   r-   r.   r     s   
zPassphrase.env_passcommandc              	   C   sr   z
t tjd}W n ttfy   Y d S w tj|dd}| }W d    n1 s-w   Y  | |dS )NZBORG_PASSPHRASE_FDr)moder   )	intrm   r   r   r\   	TypeErrorfdopenreadr  )r   fdfr   r-   r-   r.   r     s   
zPassphrase.fd_passphrasec                 C   s   |  d|S )NZBORG_NEW_PASSPHRASE)r   )r   r   r-   r-   r.   env_new_passphrase  s   zPassphrase.env_new_passphrasec              
   C   s   z
t  |}W | |S  ty?   |rt  g }dD ]}tj|d u}|d||r-dnd q|d td	|d w )N)r   r   z	{} is {}.setznot setz"Interactive password query failed. )
getpassEOFErrorprintrm   r   r   appendformatr'   ro   )r   promptZpwmsgr   Zenv_var_setr-   r-   r.   r    s   
zPassphrase.getpassc              	   C   s   d}t ||ddddrCtd| tjd tdtjd z|d	 W d S  tyB   td
t|d tjd tdtjd Y d S w 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"rr   zDMake sure the passphrase displayed above is exactly what you wanted.r   z+Your passphrase (UTF-8 encoding in hex): %s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   |   }|d ur
|S |  }|d ur|S tddD ]1}| d}|s$|rC| d}||kr;| | td |  S tdtj	d qtdtj	d qt
)	Nr      zEnter new passphrase: zEnter same passphrase again: zDRemember your passphrase. Your data will be inaccessible without it.zPassphrases do not matchr  zPassphrase must not be blank)r  r   ranger  r  r   r   r  r  r  r2   )r   allow_emptyr   r  Zpassphrase2r-   r-   r.   new8  s"   



zPassphrase.newc                 C   r{   )Nz<Passphrase "***hidden***">r-   rG   r-   r-   r.   __repr__O  r   zPassphrase.__repr__c                 C   s   t d| d|||S )Nr   r  )r   r  )rH   r   
iterationslengthr-   r-   r.   kdfR  s   zPassphrase.kdfrh   r   )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 )rc   r   r   Ni c                 C   s.   | |}t d tjdd}||| |S )Nz9WARNING: "passphrase" mode is unsupported since borg 1.0.Fr  )r   r   r   r   init)r   rT   r]   r^   r   r-   r-   r.   r[   f  s
   
zPassphraseKey.createc              	   C   s   d|j   }| |}t }|d u rt|}tddD ])}||| z|d | || ||_	|W   S  t
yF   t|}Y qw t)NzEnter passphrase for %s: r      )r   r   r   r   r  r  r&  r   r   _passphraser   r2   )r   rT   rf   r  r^   r   r  r-   r-   r.   ri   n  s    


zPassphraseKey.detectc                 C   s   G dd dt }|)Nc                   @   r&   )zAPassphraseKey.change_passphrase.<locals>.ImmutablePassphraseErrorz=The passphrase for this encryption key type can't be changed.Nr(   r-   r-   r-   r.   ImmutablePassphraseError  r/   r)  )r   )rH   r)  r-   r-   r.   change_passphrase  s   zPassphraseKey.change_passphrasec                 C   s*   |  ||j| jd |   d| _d S )Nr   F)r   r$  rl   r"  r   rk   )rH   rT   r   r-   r-   r.   r&    s   
zPassphraseKey.init)r)   r*   r+   rd   r   rZ   rR   rU   r   r"  r   r[   ri   r*  r&  r-   r-   r-   r.   rc   V  s    	

rc   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   | |}|  }d| }t }|d u r5t }|||s4tddD ]}t|}|||r1 nq"tn|||s=t|| ||_	|S )NzEnter passphrase for key %s: r   r'  )
find_keyr   r   loadr  r  r2   r0   r   r(  )r   rT   rf   r^   rw   r  r   r  r-   r-   r.   ri     s&   

zKeyfileKeyBase.detectc                 C      t rh   NotImplementedErrorrG   r-   r-   r.   r,    r   zKeyfileKeyBase.find_keyc                 C   r.  rh   r/  )rH   rw   r   r-   r-   r.   r-    r   zKeyfileKeyBase.loadc                 C   s   t |}| ||}|r?t|}t|d}|jdkrtd|j| _|j| _|j	| _	|j
| _
|j| _|dt| j| _dS dS )NZinternal_dictr   z5key version %d is not supported by this borg version.rk   TF)r   decrypt_key_filer   Zunpackbr   versionr   repository_idr   r   r   r   r   rk   rT   )rH   key_datar   cdatar}   r^   r-   r-   r.   _load  s   


zKeyfileKeyBase._loadc                 C   s   t d}|| | }t|d}|jdkrtd|j |jdkr*td|j ||j|j	d}t
|d|j}tt|||jrH|S d S )	Nr^   r1  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                      )r   r   r   r   r3  r   	algorithmr$  r   r"  r   r   r}   r   r   r!   hash)rH   r}   r   r   r   r^   r-   r-   r.   r2    s   



zKeyfileKeyBase.decrypt_key_filec           	      C   sX   t d}t}|||d}t||}t|d|}td||d||d}t	|
 S )Nr   r8  r   r   )r3  r   r"  r9  r:  r}   )rm   r   ZPBKDF2_ITERATIONSr$  r!   r   r   r   r   r   as_dict)	rH   r}   r   r   r"  r^   r:  r6  r   r-   r-   r.   encrypt_key_file  s   

zKeyfileKeyBase.encrypt_key_filec              	   C   sV   t d| j| j| j| j| j| jd}| t	|
 |}dtt|d}|S )Nr   )r3  r4  r   r   r   r   rk   r   r   )r   r4  r   r   r   r   rk   r<  r   r   r;  ro   r<   wrapr   r   )rH   r   r^   r}   r5  r-   r-   r.   _save  s   	zKeyfileKeyBase._saveNc                 C   s&   |d u r
t jdd}| | j| d S )NTr%  )r   r   saverw   )rH   r   r-   r-   r.   r*    s   z KeyfileKeyBase.change_passphrasec                 C   sb   t jdd}| |}|j|_|  |  ||}|j||dd t	d|  t	d |S )NTr%  r[   zKey in "%s" created.z>Keep this key safe. Your data will be inaccessible without it.)
r   r   rl   r4  r   r   get_new_targetr?  r   r   )r   rT   r]   r   r^   rw   r-   r-   r.   r[     s   

zKeyfileKeyBase.createFc                 C   r.  rh   r/  rH   rw   r   r[   r-   r-   r.   r?    r   zKeyfileKeyBase.savec                 C   r.  rh   r/  rH   r]   r-   r-   r.   rA    r   zKeyfileKeyBase.get_new_targetrh   r   )r)   r*   r+   r   ri   r,  r-  r7  r2  r<  r>  r*  r[   r?  rA  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 Zdd Zdd Zdd ZdddZdS )
KeyfileKeyr   zkey filerS   BORG_KEYc           	   	   C   s  | j  d }t|}t|d,}|t||kr#t| jj	 ||t||kr5t
| jj	 |W d    n1 s?w   Y  t|d}| }t|dk rftd| d t| jj	 |t|d  t|t| krtd| d t| jj	 |d	|d
d  }zt|}W n tjy   td| d t| jj	 |w t|dk rtd| d t| jj	 |W d    |S 1 sw   Y  |S )N    rbr  r   z1borg key sanity check: expected 2+ lines total. [r   r   z3borg key sanity check: key line 1 seems too long. [ r   z?borg key sanity check: key line 2+ does not look like base64. [   zWborg key sanity check: binary encrypted key data from key line 2+ suspiciously short. [)FILE_IDr  r   openr  r   r6   rT   r   r   r7   	readlinesr   r   r  ro   r   binasciir   )	rH   filenamerl   Zfile_idZrepo_idr	  linesZkey_b64r^   r-   r-   r.   sanity_check  sD   	 

zKeyfileKey.sanity_checkc                 C   sH   |   }|d ur| || jjS |  }|d ur|S t| jj t rh   )	_find_key_file_from_environmentrP  rT   rl   _find_key_in_keys_dirr5   r   r   r   rH   rS   r-   r-   r.   r,  *  s   zKeyfileKey.find_keyc                 C   s2   |   }|d ur
|S |  }|d ur|S | |S rh   )rQ  rR  _get_new_target_in_keys_dirrH   r]   rS   r-   r-   r.   get_existing_or_new_target3  s   
z%KeyfileKey.get_existing_or_new_targetc              
   C   sX   | j j}t }t|D ]}tj||}z	| ||W   S  tt	fy)   Y qw d S rh   )
rT   rl   r   rm   listdirrn   ro   rP  r6   r7   )rH   rl   Zkeys_dirnamerN  r-   r-   r.   rR  <  s   z KeyfileKey._find_key_in_keys_dirc                 C   s   |   }|d ur
|S | |S rh   )rQ  rT  rU  r-   r-   r.   rA  F  s   
zKeyfileKey.get_new_targetc                 C   s    t jd}|rt j|S d S )NZBORG_KEY_FILE)rm   r   r   rn   abspathrS  r-   r-   r.   rQ  L  s   z*KeyfileKey._find_key_file_from_environmentc                 C   sB   |j  }|}d}tj|r|d7 }|d|  }tj|s|S )Nr   z.%d)locationZto_key_filenamerm   rn   exists)rH   r]   rN  rn   ir-   r-   r.   rT  Q  s   
z&KeyfileKey._get_new_target_in_keys_dirc                 C   sX   t |}d| dd  }W d    n1 sw   Y  | ||}|r*|| _|S )NrH  r   )rK  ro   rL  r7  rw   )rH   rw   r   r	  r5  successr-   r-   r.   r-  Z  s   
zKeyfileKey.loadFc                 C   s   |rt j|rtd| | |}t|!}|| j dt| j	 d || |d W d    n1 s;w   Y  || _
d S )Nz,Aborting because key in "%s" already exists.r  r   )rm   rn   rq   r   r>  r   writerJ  r   r4  rw   )rH   rw   r   r[   r5  r	  r-   r-   r.   r?  b  s   



zKeyfileKey.saveNr   )r)   r*   r+   rd   r   rZ   rR   rV   r   rJ  rP  r,  rV  rR  rA  rQ  rT  r-  r?  r-   r-   r-   r.   rD     s    "		
	rD  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 )re   r'  Zrepokeyc                 C   s(   | j j }| j  }|st|d |S rh   )rT   r   r   load_keyr8   )rH   locr^   r-   r-   r.   r,  v  s
   

zRepoKey.find_keyc                 C   s   | j S rh   )rT   rC  r-   r-   r.   rA  ~  s   zRepoKey.get_new_targetc                 C   sT   |dk| _ | j}| }|s|j }t|d |d}| ||}|r(|| _|S NrH  r  )	r   rT   r_  r   r   r8   r   r7  rw   )rH   rw   r   r5  r`  r]  r-   r-   r.   r-    s   



zRepoKey.loadFc                 C   s2   |dk| _ | |}|d}|| || _d S ra  )r   r>  r  Zsave_keyrw   )rH   rw   r   r[   r5  r-   r-   r.   r?    s
   




zRepoKey.saveNr   )r)   r*   r+   rd   r   rZ   rR   rW   r   r,  rA  r-  r?  r-   r-   r-   r.   re   p  s    re   c                   @   s&   e Zd ZdZdZdZejZdZ	e
ZdS )Blake2KeyfileKey   zkey file BLAKE2bzkeyfile-blake2rE  N)r)   r*   r+   rd   r   rZ   rR   rV   r   rJ  r%   r   r-   r-   r-   r.   rb    s    rb  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+   rd   r   rZ   rR   rW   r   r%   r   r-   r-   r-   r.   rd    s    rd  c                       s\   e Zd ZejZdZ fddZ fddZd fdd	Z	dd	d
Z
dd ZdddZ  ZS )AuthenticatedKeyBaseFc                    sB   t rtd}|| _|| _|| _|| _d| _d| _dS t 	||S )Nr   r   FT)
r   ru   r4  r   r   r   r   rk   rE   r7  )rH   r5  r   ZNOPErI   r-   r.   r7    s   zAuthenticatedKeyBase._loadc                    s   t  ||}d| _|S r   )rE   r-  r   )rH   rw   r   r]  rI   r-   r.   r-    s   zAuthenticatedKeyBase.loadc                    s   t  j|||d d| _d S )Nr@  F)rE   r?  r   rB  rI   r-   r.   r?    s   
zAuthenticatedKeyBase.saveNc                 C   s&   |d ur|d | j krtdd S d S )Nr   r   )rd   r   )rH   rf   r-   r-   r.   r     s   z!AuthenticatedKeyBase.init_ciphersc                 C   r   r   r   r   r-   r-   r.   r     r   zAuthenticatedKeyBase.encryptTc                 C   sh   |d | j kr|d urt|nd}td| t|dd  }|s#|S | |}tr,|S | || |S )Nr   r   zChunk %s: Invalid enveloper   )rd   r   r   r   ry   r   r   r   r-   r-   r.   r     s   
zAuthenticatedKeyBase.decryptr   rh   r   )r)   r*   r+   rR   rW   r   r   r7  r-  r?  r   r   r   rM   r-   r-   rI   r.   rf    s    
rf  c                   @   s   e Zd ZdZdZdZdS )AuthenticatedKey   ZauthenticatedNr)   r*   r+   rd   r   rZ   r-   r-   r-   r.   rg    rX   rg  c                   @   rQ   )Blake2AuthenticatedKey   zauthenticated BLAKE2bzauthenticated-blake2Nri  r-   r-   r-   r.   rj    rX   rj  )\rM  configparserr  r   rm   r   r  r<   r   r   r   r   Zhashlibr   r   r   r   r	   	constantsr   r   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   r8   r:   r@   rB   rO   rP   rR   r_   rb   rg   rj   rp   rk   rs   r   r   r   r   r   r   r   rc   r+  rD  re   rb  rd  rf  rg  rj  rY   r-   r-   r-   r.   <module>   s    (			 &,Em7sp+
	2