forked from borgbackup/borg
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update of 1.2-maint as suggested in borgbackup#6667
- Loading branch information
Christopher Klooz
authored
May 14, 2022
1 parent
bcac974
commit 283fd81
Showing
1 changed file
with
98 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,32 +124,116 @@ prompt is a set BORG_PASSPHRASE. See issue :issue:`2169` for details. | |
Encryption | ||
---------- | ||
|
||
Encryption is currently based on the Encrypt-then-MAC construction, | ||
AEAD modes | ||
~~~~~~~~~~ | ||
|
||
Modes: --encryption (repokey|keyfile)-[blake2-](aes-ocb|chacha20-poly1305) | ||
|
||
Supported: borg 1.3+ | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
Encryption with these modes is based on AEAD ciphers (authenticated encryption | ||
with associated data) and session keys. | ||
|
||
Depending on the chosen mode (see :ref:`borg_init`) different AEAD ciphers are used: | ||
|
||
- AES-256-OCB - super fast, single-pass algorithm IF you have hw accelerated AES. | ||
- chacha20-poly1305 - very fast, purely software based AEAD cipher. | ||
|
||
The chunk ID is derived via a MAC over the plaintext (mac key taken from borg key): | ||
|
||
- HMAC-SHA256 - super fast IF you have hw accelerated SHA256 (see section "Encryption" below). | ||
- Blake2b - very fast, purely software based algorithm. | ||
|
||
For each borg invocation, a new session id is generated by `os.urandom`_. | ||
|
||
From that session id, the initial key material (ikm, taken from the borg key) | ||
and an application and cipher specific salt, borg derives a session key via HKDF. | ||
|
||
For each session key, IVs (nonces) are generated by a counter which increments for | ||
each encrypted message. | ||
|
||
Session:: | ||
|
||
sessionid = os.urandom(24) | ||
ikm = enc_key || enc_hmac_key | ||
salt = "borg-session-key-CIPHERNAME" | ||
sessionkey = HKDF(ikm, sessionid, salt) | ||
message_iv = 0 | ||
|
||
Encryption:: | ||
|
||
id = MAC(id_key, data) | ||
compressed = compress(data) | ||
|
||
header = type-byte || 00h || message_iv || sessionid | ||
aad = id || header | ||
message_iv++ | ||
encrypted, auth_tag = AEAD_encrypt(session_key, message_iv, compressed, aad) | ||
authenticated = header || auth_tag || encrypted | ||
|
||
Decryption:: | ||
|
||
# Given: input *authenticated* data and a *chunk-id* to assert | ||
type-byte, past_message_iv, past_sessionid, auth_tag, encrypted = SPLIT(authenticated) | ||
|
||
ASSERT(type-byte is correct) | ||
|
||
past_key = HKDF(ikm, past_sessionid, salt) | ||
decrypted = AEAD_decrypt(past_key, past_message_iv, authenticated) | ||
|
||
decompressed = decompress(decrypted) | ||
|
||
ASSERT( CONSTANT-TIME-COMPARISON( chunk-id, MAC(id_key, decompressed) ) ) | ||
|
||
Notable: | ||
|
||
- More modern and often faster AEAD ciphers instead of self-assembled stuff. | ||
- Due to the usage of session keys, IVs (nonces) do not need special care here as | ||
they did for the legacy encryption modes. | ||
- The id is now also input into the authentication tag computation. | ||
This strongly associates the id with the written data (== associates the key with | ||
the value). When later reading the data for some id, authentication will only | ||
succeed if what we get was really written by us for that id. | ||
|
||
|
||
Legacy modes | ||
~~~~~~~~~~~~ | ||
|
||
Modes: --encryption (repokey|keyfile)-[blake2] | ||
|
||
Supported: all borg versions, blake2 since 1.1 | ||
|
||
DEPRECATED. We strongly suggest you use the safer AEAD modes, see above. | ||
This comment has been minimized.
Sorry, something went wrong.
ThomasWaldmann
|
||
|
||
Encryption with these modes is based on the Encrypt-then-MAC construction, | ||
which is generally seen as the most robust way to create an authenticated | ||
encryption scheme from encryption and message authentication primitives. | ||
|
||
Every operation (encryption, MAC / authentication, chunk ID derivation) | ||
uses independent, random keys generated by `os.urandom`_ [#]_. | ||
uses independent, random keys generated by `os.urandom`_. | ||
|
||
Borg does not support unauthenticated encryption -- only authenticated encryption | ||
schemes are supported. No unauthenticated encryption schemes will be added | ||
in the future. | ||
|
||
Depending on the chosen mode (see :ref:`borg_init`) different primitives are used: | ||
|
||
- The actual encryption is currently always AES-256 in CTR mode. The | ||
- Legacy encryption modes use AES-256 in CTR mode. The | ||
counter is added in plaintext, since it is needed for decryption, | ||
and is also tracked locally on the client to avoid counter reuse. | ||
|
||
- The authentication primitive is either HMAC-SHA-256 or BLAKE2b-256 | ||
in a keyed mode. HMAC-SHA-256 uses 256 bit keys, while BLAKE2b-256 | ||
uses 512 bit keys. | ||
|
||
The latter is secure not only because BLAKE2b itself is not | ||
susceptible to `length extension`_, but also since it truncates the | ||
hash output from 512 bits to 256 bits, which would make the | ||
construction safe even if BLAKE2b were broken regarding length | ||
extension or similar attacks. | ||
in a keyed mode. | ||
|
||
Both HMAC-SHA-256 and BLAKE2b have undergone extensive cryptanalysis | ||
and have proven secure against known attacks. The known vulnerability | ||
of SHA-256 against length extension attacks does not apply to HMAC-SHA-256. | ||
|
||
The authentication primitive should be chosen based upon SHA hardware support: | ||
all AMD Ryzen, Intel 10th+ generation mobile and Intel 11th+ generation | ||
desktop processors, Apple M1+ and most current ARM64 architectures support | ||
SHA extensions and are likely to perform best with HMAC-SHA-256. | ||
64-bit CPUs without SHA extensions are likely to perform best with BLAKE2b. | ||
|
||
- The primitive used for authentication is always the same primitive | ||
that is used for deriving the chunk ID, but they are always | ||
|
@@ -208,13 +292,6 @@ untrusted, but a trusted synchronization channel exists between | |
clients, the security database could be synchronized between them over | ||
said trusted channel. This is not part of Borg's functionality. | ||
|
||
.. [#] Using the :ref:`borg key migrate-to-repokey <borg_key_migrate-to-repokey>` | ||
command a user can convert repositories created using Attic in "passphrase" | ||
mode to "repokey" mode. In this case the keys were directly derived from | ||
the user's passphrase at some point using PBKDF2. | ||
Borg does not support "passphrase" mode otherwise any more. | ||
.. _key_encryption: | ||
|
||
Offline key security | ||
|
@@ -260,7 +337,7 @@ Implementations used | |
We do not implement cryptographic primitives ourselves, but rely | ||
on widely used libraries providing them: | ||
|
||
- AES-CTR and HMAC-SHA-256 from OpenSSL 1.0 / 1.1 are used, | ||
- AES-CTR, AES-OCB, CHACHA20-POLY1305 and HMAC-SHA-256 from OpenSSL 1.1 are used, | ||
which is also linked into the static binaries we provide. | ||
We think this is not an additional risk, since we don't ever | ||
use OpenSSL's networking, TLS or X.509 code, but only their | ||
|
@@ -275,7 +352,8 @@ on widely used libraries providing them: | |
|
||
Implemented cryptographic constructions are: | ||
|
||
- Encrypt-then-MAC based on AES-256-CTR and either HMAC-SHA-256 | ||
- AEAD modes: AES-OCB and CHACHA20-POLY1305 are straight from OpenSSL. | ||
- Legacy modes: Encrypt-then-MAC based on AES-256-CTR and either HMAC-SHA-256 | ||
or keyed BLAKE2b256 as described above under Encryption_. | ||
- Encrypt-and-MAC based on AES-256-CTR and HMAC-SHA-256 | ||
as described above under `Offline key security`_. | ||
|
yeah, it was planned to be 1.3.
considering my recent "breaking" PRs it might well be (if we merge these) that it will be 2.0.