mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-19 21:39:18 +00:00
Merge pull request #1286 from Granddave/feature/update-vault-docs
Update vault documentation
This commit is contained in:
commit
243a52ebed
1 changed files with 177 additions and 58 deletions
233
docs/vault.md
233
docs/vault.md
|
@ -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
|
||||
|
||||
|
@ -36,15 +38,16 @@ This is a reasonable assumption to make, because it's highly unlikely that an
|
|||
Aegis user will ever come close to saving the vault 2<sup>32</sup> times.
|
||||
|
||||
_Switching to a nonce misuse-resistant cipher like AES-GCM-SIV or a cipher with
|
||||
a larger (192 bits) nonce like XChaCha-Poly1305 will be considered in the future._
|
||||
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,
|
||||
with the following parameters:
|
||||
[__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 |
|
||||
| :-------- | :------------- |
|
||||
| Parameter | Value |
|
||||
|:----------|:---------------|
|
||||
| N | 2<sup>15</sup> |
|
||||
| r | 8 |
|
||||
| p | 1 |
|
||||
|
@ -104,12 +107,17 @@ shown below:
|
|||
}
|
||||
```
|
||||
|
||||
It starts with a ``version`` number and a ``header``. 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.
|
||||
It starts with a ``version`` number. If a forwards incompatible change is
|
||||
introduced to the vault format, the version number will be incremented. The
|
||||
current version of the vault format is ``1``.
|
||||
|
||||
The [``header``](#header), if not empty, contains the list of slots and the
|
||||
encryption parameters used for decrypting 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 [vault content](#vault-content) for details.
|
||||
|
||||
Full examples of a [plain text
|
||||
vault](/app/src/test/resources/com/beemdevelopment/aegis/importers/aegis_plain.json)
|
||||
|
@ -122,9 +130,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.
|
||||
|
@ -143,11 +156,11 @@ encrypted and Aegis will try to parse it as such.
|
|||
|
||||
The different slot types are identified with a numerical ID.
|
||||
|
||||
| Type | ID |
|
||||
| :---------- | :--- |
|
||||
| Raw | 0x00 |
|
||||
| Password | 0x01 |
|
||||
| Biometric | 0x02 |
|
||||
| Type | ID |
|
||||
|:----------|:-----|
|
||||
| Raw | 0x00 |
|
||||
| Password | 0x01 |
|
||||
| Biometric | 0x02 |
|
||||
|
||||
##### Raw
|
||||
|
||||
|
@ -182,7 +195,7 @@ 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``
|
||||
against rainbow table attacks. It's stored along with the ``N``, ``r`` and ``p``
|
||||
parameters.
|
||||
|
||||
```json
|
||||
|
@ -201,56 +214,69 @@ parameters.
|
|||
}
|
||||
```
|
||||
|
||||
### Content
|
||||
### Vault 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 forwards incompatible change is introduced to the content format, the version
|
||||
number will be incremented. The current version of the vault content format is
|
||||
``3``.
|
||||
|
||||
| Field | Type | Description |
|
||||
|:------------|:------|:-----------------------------------------|
|
||||
| ``version`` | int | The version of the vault content 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 hold the following fields:
|
||||
|
||||
| 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`` | bool | Whether the entry is a favorite or not. |
|
||||
| ``info`` | object | Information specific to the OTP type. |
|
||||
| ``groups`` | array | 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 types:
|
||||
|
||||
| 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
|
||||
| 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 |
|
||||
| MOTP | "motp" | 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)
|
||||
|
||||
The following algorithms are supported for HOTP and TOTP:
|
||||
|
||||
| Algorithm | ID |
|
||||
| :-------- | :------- |
|
||||
| SHA-1 | "SHA1" |
|
||||
| SHA-256 | "SHA256" |
|
||||
| SHA-512 | "SHA512" |
|
||||
|
||||
For Steam, only SHA-1 is supported. For Yandex, only SHA-256 is supported.
|
||||
| Field | Type | Description |
|
||||
|:-----------|:-------|:-----------------------------------|
|
||||
| ``secret`` | string | The Base32 encoded secret. |
|
||||
| ``algo`` | string | The hashing algorithm. |
|
||||
| ``digits`` | int | The number of digits in the token. |
|
||||
|
||||
Example of a TOTP entry:
|
||||
|
||||
|
@ -260,12 +286,105 @@ 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"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
##### 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:
|
||||
|
||||
| Algorithm | ID |
|
||||
|:----------|:---------|
|
||||
| SHA-1 | "SHA1" |
|
||||
| SHA-256 | "SHA256" |
|
||||
| SHA-512 | "SHA512" |
|
||||
|
||||
##### 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](/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/OTP.java).
|
||||
|
||||
A couple of fields have fixed values:
|
||||
|
||||
| Field | Value |
|
||||
|:-----------|:-------|
|
||||
| ``algo`` | "SHA1" |
|
||||
| ``period`` | 30 |
|
||||
| ``digits`` | 5 |
|
||||
|
||||
##### MOTP
|
||||
|
||||
There is no specification available for MOTP. Aegis' implementation of it can be
|
||||
found in
|
||||
[crypto/otp/MOTP.java](/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/MOTP.java).
|
||||
|
||||
A couple of fields have fixed values:
|
||||
|
||||
| Field | Value |
|
||||
|:-----------|:------|
|
||||
| ``algo`` | "MD5" |
|
||||
| ``period`` | 10 |
|
||||
| ``digits`` | 6 |
|
||||
|
||||
MOTP-specific fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
|:--------|:-------|:------------|
|
||||
| ``pin`` | string | 4-digit PIN |
|
||||
|
||||
##### Yandex
|
||||
|
||||
There is no specification available for Yandex's OTP algorithm. Aegis'
|
||||
implementation can be found in
|
||||
[crypto/otp/YAOTP.java](/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/YAOTP.java)
|
||||
|
||||
A couple of fields have fixed values:
|
||||
|
||||
| Field | Value |
|
||||
|:-----------|:---------|
|
||||
| ``algo`` | "SHA256" |
|
||||
| ``period`` | 30 |
|
||||
| ``digits`` | 8 |
|
||||
|
||||
Yandex-specific fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
|:--------|:-------|:---------------|
|
||||
| ``pin`` | string | 4-16 digit PIN |
|
||||
|
||||
#### Groups
|
||||
|
||||
A group consists of a ``name`` and a randomly generated ``uuid`` (version 4).
|
||||
|
||||
| Field | Type | Description |
|
||||
|:---------|:-------|:-----------------------|
|
||||
| ``uuid`` | string | A UUID (version 4). |
|
||||
| ``name`` | string | The name of the group. |
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"uuid": "01234567-89ab-cdef-0123-456789abcdef",
|
||||
"name": "Personal"
|
||||
}
|
||||
```
|
||||
|
|
Loading…
Add table
Reference in a new issue