diff --git a/docs/global.rst.inc b/docs/global.rst.inc index 694f4d9..15f38ea 100644 --- a/docs/global.rst.inc +++ b/docs/global.rst.inc @@ -12,6 +12,10 @@ .. _github: https://github.com/jborg/attic .. _OpenSSL: https://www.openssl.org/ .. _Python: http://www.python.org/ +.. _PBKDF2: https://en.wikipedia.org/wiki/PBKDF2 +.. _SHA256: https://en.wikipedia.org/wiki/SHA-256 +.. _HMAC: https://en.wikipedia.org/wiki/HMAC +.. _msgpack: http://msgpack.org/ .. _`msgpack-python`: https://pypi.python.org/pypi/msgpack-python/ .. _llfuse: https://pypi.python.org/pypi/llfuse/ .. _homebrew: http://mxcl.github.io/homebrew/ diff --git a/docs/internals.rst b/docs/internals.rst new file mode 100644 index 0000000..c255487 --- /dev/null +++ b/docs/internals.rst @@ -0,0 +1,69 @@ +.. include:: global.rst.inc +.. _internals: + +Internals +========= + + +Key files +--------- + +When initialized with the ``init -e keyfile`` command, |project_name| +needs an associated file in ``$HOME/.attic/keys`` to read and write +the repository. As with most crypto code in |project_name|, the format +of those files is defined in `attic/key.py`_. The format is based on +msgpack_, base64 encoding and PBKDF2_ SHA256 encryption, which is +then encoded again in a msgpack_. + +The internal data structure is as follows: + +version + currently always an integer, 1 + +repository_id + the ``id`` field in the ``config`` ``INI`` file of the repository. + +enc_key + the AES encryption key + +enc_hmac_key + the HMAC key (32 bytes) + +id_key + another HMAC key? unclear. + +chunk_seed + unknown + +Those fields are encoded using msgpack_. The utf-8-encoded phassphrase +is encrypted with a PBKDF2_ and SHA256_ using 100000 iterations and a +random 32 bytes salt to give us a derived key. The derived key is 32 +bytes long. A HMAC_ SHA256_ checksum of the above fields is generated +with the derived key, then the derived key is also used to encrypt the +above pack of fields. Then the result is stored in a another msgpack_ +formatted as follows: + +version + currently always an integer, 1 + +salt + random 32 bytes salt used to encrypt the passphrase + +iterations + number of iterations used to encrypt the passphrase + +algorithm + the hashing algorithm used to encrypt the passphrase and do the HMAC + checksum + +hash + the HMAC checksum of the encrypted passphrase key + +data + the passphrase key, encrypted with AES over a PBKDF2_ SHA256 hash + described above + +The resulting msgpack_ is then encoded using base64 and written to the +key file, wrapped using the textwrap_ module with a header. The header +is a single line with the string ``ATTIC_KEY``, a space and a +hexadecimal representation of the repository id.