Skip to content

Commit

Permalink
Update vault documentation
Browse files Browse the repository at this point in the history
Here some changes to the vault documentation are made. The documentation
is updated to reflect the latest versions of both the vault and the
database, i.e. vault version 1 and database version 3.
  • Loading branch information
Granddave committed Feb 27, 2024
1 parent 224ec25 commit bfcb074
Showing 1 changed file with 122 additions and 39 deletions.
161 changes: 122 additions & 39 deletions docs/vault.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ format of the vault.
### Primitives

Two cryptographic primitives were selected for use in Aegis. An Authenticated
Encryption with Associated Data (AEAD) cipher and a Key Derivation Function
(KDF).
Encryption with Associated Data
([AEAD](https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data))
cipher and a Key Derivation Function
([KDF](https://en.wikipedia.org/wiki/Key_derivation_function)).

#### AEAD

Expand All @@ -40,7 +42,7 @@ a larger (192 bits) nonce like XChaCha-Poly1305 will be considered in the future

#### KDF

__scrypt__ is used as the KDF to derive a key from a user-provided password,
[__scrypt__](https://en.wikipedia.org/wiki/Scrypt) is used as the KDF to derive a key from a user-provided password,
with the following parameters:

| Parameter | Value |
Expand Down Expand Up @@ -104,12 +106,17 @@ shown below:
}
```

It starts with a ``version`` number and a ``header``. If a backwards
It starts with a ``version`` number. If a backwards
incompatible change is introduced to the content format, the version number will
be incremented. The vault contents are stored under ``db``. Its value depends on
whether the vault is encrypted or not. If it is, the value is a string containing
the Base64 encoded (with padding) ciphertext of the vault contents. Otherwise,
the value is a JSON object.
be incremented. The current version of the vault format is ``1``.

The [``header``](#header), if not empty, contains information about the encryption parameters and the
different ways to unlock the vault.

The vault contents are stored under ``db``. Its value depends on whether the
vault is encrypted or not. If it is, the value is a string containing the
Base64 encoded (with padding) ciphertext of the vault contents. Otherwise, the
value is a JSON object. See [database contents](#database-content) for details.

Full examples of a [plain text
vault](/app/src/test/resources/com/beemdevelopment/aegis/importers/aegis_plain.json)
Expand All @@ -122,9 +129,14 @@ password: [decrypt.py](/docs/decrypt.py).

### Header

The header starts with the list of ``slots``. It also has a ``params`` object
that holds the ``nonce`` and ``tag`` that were produced during encryption,
encoded as a hexadecimal string.
The header starts with the list of [``slots``](#slots-1). Each slot contains the
master key in an encrypted form together with the key wrapping parameters.

It also has a ``params`` object that holds the ``nonce`` and ``tag`` that were
produced during the AES-GCM encryption, encoded as a hexadecimal string. These
encryption parameters together with the master key (which can be retrieved by
decrypting the ``key`` from one of the slots) are used to decrypt the vault
contents found in the ``db`` field.

Setting ``slots`` and ``params`` to null indicates that the vault is not
encrypted and Aegis will try to parse it as such.
Expand All @@ -141,7 +153,7 @@ encrypted and Aegis will try to parse it as such.

#### Slots

The different slot types are identified with a numerical ID.
The different slot types are identified with a numerical ID.

| Type | ID |
| :---------- | :--- |
Expand Down Expand Up @@ -182,8 +194,8 @@ Raw slots don't imply use of a particular storage type.

As noted earlier, scrypt is used to derive a 256-bit key from a user-provided
password. A random 256-bit ``salt`` is generated and passed to scrypt to protect
against rainbow table attacks. Its stored along with the ``N``, ``r`` and ``p``
parameters.
against rainbow table attacks. It's stored along with the ``N``, ``r`` and
``p`` parameters.

```json
{
Expand All @@ -201,46 +213,76 @@ parameters.
}
```

### Content
### Database Content

The content is a JSON object encoded in UTF-8.

```json
{
"version": 1,
"entries": []
"version": 3,
"entries": [],
"groups": []
}
```

It has a ``version`` number and a list of ``entries``. If a backwards
incompatible change is introduced to the content format, the version number will
be incremented.
It has a ``version`` number, a list of ``entries`` and a list of ``groups``. If
a backwards incompatible change is introduced to the content format, the
version number will be incremented. The current version of the database format
is ``3``.


| Field | Type | Description |
| :------------ | :------ | :---------------------------------- |
| ``version`` | Integer | The version of the database format. |
| ``entries`` | Array | A list of [entries](#entries). |
| ``groups`` | Array | A list of [groups](#groups). |


#### Entries

Each entry has a unique randomly generated ``UUID`` (version 4), as well as a
``name`` and ``issuer`` to identify the account name and service that the token
is for. Entries can also have an icon. These are JPEG's encoded in Base64 with
padding. The ``info`` object holds information specific to the OTP type. The
``secret`` is encoded in Base32 without padding.
Each entry has a unique randomly generated ``UUID``, as well as a ``name`` and
``issuer`` to identify the account name and service that the token is for.

Entries holds the following fields:

There are a number of supported types:
| Field | Type | Description |
| :------------ | :------------- | :--------------------------------------------------------- |
| ``type`` | String | The type of the OTP algorithm. See table below. |
| ``uuid`` | String | A UUID (version 4). |
| ``name`` | String | The account name. |
| ``issuer`` | String | The service that the token is for. |
| ``note`` | String | A personal note about the entry. |
| ``icon`` | String \| null | JPEG's encoded in Base64 with padding. |
| ``icon_mime`` | String \| null | The MIME type of the icon. Is null if ``icon`` is null. |
| ``icon_hash`` | String \| null | The SHA-256 hash of the icon. Is null if ``icon`` is null. |
| ``favorite`` | Boolean | Whether the entry is a favorite or not. |
| ``info`` | Object | Information specific to the OTP type. |
| ``groups`` | List | A list of UUIDs of groups that the entry is a member of. See [Groups](#groups). |

The ``info`` object contains different fields depending on the type of the OTP.

There are a number of supported ``type``s:

| Type | ID | Spec |
| :------------------ | :------- | :-------- |
| HOTP | "hotp" | [RFC 4226](https://datatracker.ietf.org/doc/html/rfc4226)
| TOTP | "totp" | [RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238)
| Steam | "steam" | N/A
| Yandex | "yandex" | N/A
| HOTP | "hotp" | [RFC 4226](https://datatracker.ietf.org/doc/html/rfc4226) |
| TOTP | "totp" | [RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238) |
| Steam | "steam" | N/A |
| Yandex | "yandex" | N/A |

There is no specification available for Steam's OTP algorithm. It's essentially
the same as TOTP, but it uses a different final encoding step. Aegis'
implementation of it can be found in
[crypto/otp/OTP.java](https://github.com/beemdevelopment/Aegis/blob/master/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/OTP.java).
Common ``info`` fields for all types:

There is also no specification available for Yandex's OTP algorithm. Aegis'
implementation can be found in
[crypto/otp/YAOTP.java](https://github.com/beemdevelopment/Aegis/blob/master/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/YAOTP.java)
| Field | Type | Description |
| :------------ | :------ | :-------------------------------- |
| ``secret`` | String | The Base32 encoded secret. |
| ``algo`` | String | The hashing algorithm. |
| ``digits`` | Integer | The number of digits in the token.|


##### HOTP and TOTP

TOTP uses the ``period`` field, which is the time step in seconds. HOTP uses
the ``counter`` field, which is incremented every time a token is generated.

The following algorithms are supported for HOTP and TOTP:

Expand All @@ -250,7 +292,24 @@ The following algorithms are supported for HOTP and TOTP:
| SHA-256 | "SHA256" |
| SHA-512 | "SHA512" |

For Steam, only SHA-1 is supported. For Yandex, only SHA-256 is supported.
##### Steam

There is no specification available for Steam's OTP algorithm. It's essentially
the same as TOTP, but it uses a different final encoding step. Aegis'
implementation of it can be found in
[crypto/otp/OTP.java](https://github.com/beemdevelopment/Aegis/blob/master/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/OTP.java).

Only SHA-1 is supported.

##### Yandex

There is also no specification available for Yandex's OTP algorithm. Aegis'
implementation can be found in
[crypto/otp/YAOTP.java](https://github.com/beemdevelopment/Aegis/blob/master/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/YAOTP.java)

only SHA-256 is supported.

##### Example entry

Example of a TOTP entry:

Expand All @@ -260,12 +319,36 @@ Example of a TOTP entry:
"uuid": "01234567-89ab-cdef-0123-456789abcdef",
"name": "Bob",
"issuer": "Google",
"note": "Main account",
"favorite": false,
"icon": null,
"icon_mime": null,
"icon_hash": null,
"info": {
"secret": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
"algo": "SHA1",
"digits": 6,
"period": 30
}
},
"groups": [
"01234567-89ab-cdef-0123-456789abcdef"
]
}
```

#### Groups

A group contains of a ``name`` and a randomly generated ``uuid`` (version 4).

```json
{
"uuid": "01234567-89ab-cdef-0123-456789abcdef",
"name": "Personal"
}
```

| Field | Type | Description |
| :------------ | :------ | :-----------------------|
| ``uuid`` | String | A UUID (version 4). |
| ``name`` | String | The name of the group. |

0 comments on commit bfcb074

Please sign in to comment.