cleanup markdown formatting

parent f2ffb282
...@@ -39,7 +39,7 @@ The index is used so one can generate more keys corresponding to the same URI. ...@@ -39,7 +39,7 @@ The index is used so one can generate more keys corresponding to the same URI.
##HD Structure ##HD Structure
1. First concatenate `index` with the URI (`uri`). Use little endian for `index`. 1. First concatenate `index` with the URI (`uri`). Use little endian for `index`.
2. Compute the SHA256 hash of the result (`hash`). 2. Compute the SHA256 hash of the result (`hash`).
...@@ -52,7 +52,7 @@ The index is used so one can generate more keys corresponding to the same URI. ...@@ -52,7 +52,7 @@ The index is used so one can generate more keys corresponding to the same URI.
6. Derive the HD node `m/13'/A'/B'/C'/D'` according to BIP32. 6. Derive the HD node `m/13'/A'/B'/C'/D'` according to BIP32.
###Worked example ###Worked example
1. `index + uri`=`0` + `https://satoshi@bitcoin.org/login` 1. `index + uri`=`0` + `https://satoshi@bitcoin.org/login`
2. `sha256(index + uri)` = `d0e2389d4c8394a9f3e32de01104bf6e8db2d9e2bb0905d60fffa5a18fd696db` 2. `sha256(index + uri)` = `d0e2389d4c8394a9f3e32de01104bf6e8db2d9e2bb0905d60fffa5a18fd696db`
...@@ -62,7 +62,7 @@ The index is used so one can generate more keys corresponding to the same URI. ...@@ -62,7 +62,7 @@ The index is used so one can generate more keys corresponding to the same URI.
5. `A'` = 2637750992, `B'` = 2845082444, `C'` = 3761103859, `D'` = 4005495825 5. `A'` = 2637750992, `B'` = 2845082444, `C'` = 3761103859, `D'` = 4005495825
6. `bip32 node path` = `m/2147483661/2637750992/2845082444/3761103859/4005495825` 6. `bip32 node path` = `m/2147483661/2637750992/2845082444/3761103859/4005495825`
See a [Python example](https://github.com/trezor/python-trezor/blob/ca45019918bc4c54f1ace899a9acf397c8f4d92f/tests/test_msg_signidentity.py#L27). See a [Python example](https://github.com/trezor/python-trezor/blob/ca45019918bc4c54f1ace899a9acf397c8f4d92f/tests/test_msg_signidentity.py#L27).
......
...@@ -13,7 +13,6 @@ Created: 2016-18-02 ...@@ -13,7 +13,6 @@ Created: 2016-18-02
SLIP-0016 describes simple encryption concept for hardware device for secure storage of passwords. SLIP-0016 describes simple encryption concept for hardware device for secure storage of passwords.
## General design ## General design
At first, we derive a master key from HW device itself, which is divided in two parts. At first, we derive a master key from HW device itself, which is divided in two parts.
...@@ -22,55 +21,51 @@ Second part is used for primary storage encryption. ...@@ -22,55 +21,51 @@ Second part is used for primary storage encryption.
Storage file is encrypted JSON object, which contains configuration, tags and separate entries. Each entry has other two encrypted properties derivated from device to provide higher level of security with low risk of leaks. Storage file is encrypted JSON object, which contains configuration, tags and separate entries. Each entry has other two encrypted properties derivated from device to provide higher level of security with low risk of leaks.
## Design details ## Design details
#### Deriving master key ### Deriving master key
We derive masterKey from hardware device by sending cipherKeyValue with following params: We derive masterKey from hardware device by sending cipherKeyValue with following params:
- path: ```m/10016'/0``` (hardened path, see BIP32) - path: `m/10016'/0` (hardened path, see BIP32)
- ENC_KEY: ```'Unlock encrypted storage?'``` (max length message is 256 bytes) - ENC_KEY: `'Unlock encrypted storage?'` (max length message is 256 bytes)
- ENC_VALUE: ```'2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee'``` (in hexadecimal (128 /2), max length is 1024 bytes) - ENC_VALUE: `'2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee'` (in hexadecimal (128 /2), max length is 1024 bytes)
- encrypt: ```true``` - encrypt: `true`
- ask_on_encrypt: ```true``` - ask_on_encrypt: `true`
- ask_on_decrypt: ```true``` - ask_on_decrypt: `true`
- iv: unset - iv: unset
JS EXAMPLE: JS EXAMPLE:
```javascript
``` javascript
session.cipherKeyValue( session.cipherKeyValue(
[(10016 | 0x80000000) >>> 0, 0], [(10016 | 0x80000000) >>> 0, 0],
'Unlock encrypted storage?', 'Unlock encrypted storage?',
'2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee', '2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee',
true, true, true) true, true, true)
``` ```
CipherKeyValue will be defined in SLIP-0011; right now you can check the source code in trezor source code_. CipherKeyValue will be defined in SLIP-0011; right now you can check the source code in [trezor source code](https://github.com/trezor/trezor-mcu/blob/master/firmware/fsm.c#L451-L483).
.. _trezor source code: https://github.com/trezor/trezor-mcu/blob/master/firmware/fsm.c#L451-L483
### Deriving file name
#### Deriving file name
From the first half of master key, we derive the file name for every user/device in the following way: From the first half of master key, we derive the file name for every user/device in the following way:
First, we use the HMAC function: First, we use the HMAC function:
```HMAC-SHA256(fileKey, FILENAME_MESS)``` `HMAC-SHA256(fileKey, FILENAME_MESS)`
where: where:
- fileKey is the first half of masterKey
(```masterKey.substring(0, masterKey.length / 2)```)
- FILENAME_MESS is a constant string ```'5f91add3fa1c3c76e90c90a3bd0999e2bd7833d06a483fe884ee60397aca277a'```
The output result is digested to HEX string. After, we append extension ```'.pswd'``` - fileKey is the first half of masterKey (`masterKey.substring(0, masterKey.length / 2)`)
- FILENAME_MESS is a constant string `'5f91add3fa1c3c76e90c90a3bd0999e2bd7833d06a483fe884ee60397aca277a'`
EXAMPLE RESULT: ```a80387a2222f4360f71fd2165368c6ed91b26287d9bc1ce8be71e64e6b216a4f.pswd``` The output result is digested to HEX string. After, we append extension `'.pswd'`
EXAMPLE RESULT: `a80387a2222f4360f71fd2165368c6ed91b26287d9bc1ce8be71e64e6b216a4f.pswd`
#### Deriving encryption key and file level encryption ### Deriving encryption key and file level encryption
As an encryption key is used the SECOND half (32 bytes) of master key for the first level of data file encryption. Encrpytion key is in HEX string. As an encryption key is used the SECOND half (32 bytes) of master key for the first level of data file encryption. Encrpytion key is in HEX string.
For encrypt/decrypt we are using ```AES-256-GCM``` algorithm. For encrypt/decrypt we are using `AES-256-GCM` algorithm.
- Input Vector (IV) is 12 randomly generated bytes - Input Vector (IV) is 12 randomly generated bytes
- GCM is used with full 128-bit autentication tag (authTag) - GCM is used with full 128-bit autentication tag (authTag)
...@@ -78,29 +73,29 @@ For encrypt/decrypt we are using ```AES-256-GCM``` algorithm. ...@@ -78,29 +73,29 @@ For encrypt/decrypt we are using ```AES-256-GCM``` algorithm.
for more: https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv for more: https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv
The result output stored in file is: The result output stored in file is:
- first 12 bytes of the file is randomly generated IV - first 12 bytes of the file is randomly generated IV
- next 16 bytes is the GCM authTag - next 16 bytes is the GCM authTag
- the rest is output ciphertext - the rest is output ciphertext
for more: https://nodejs.org/api/crypto.html#crypto_crypto_createdecipheriv_algorithm_key_iv for more: https://nodejs.org/api/crypto.html#crypto_crypto_createdecipheriv_algorithm_key_iv
### Data format
#### Data format
(Decrypted) data file is serialized JSON object with the following keys: (Decrypted) data file is serialized JSON object with the following keys:
- ```version```: for future backwards compatibility and data storage manipualtion - `version`: for future backwards compatibility and data storage manipualtion
- ```config```: for remembering personal setup of application - `config`: for remembering personal setup of application
- ```tags```: contain set of labels with their icons (from icomoon set). Default tag is **All** and it is only tag, unable to edit or delete. - `tags`: contain set of labels with their icons (from icomoon set). Default tag is **All** and it is only tag, unable to edit or delete.
```javascript ``` javascript
{title:"My social networks", icon:"person", active:"active"} {title:"My social networks", icon:"person", active:"active"}
``` ```
- ```entries```: is object of all password entries encrypted second time - `entries`: is object of all password entries encrypted second time
```javascript ``` javascript
{ {
"title": "http://wwww.github.com", "title": "http://wwww.github.com",
"username": "Satoshi Nakamoto", "username": "Satoshi Nakamoto",
"nonce": "8688105887642a3cbb61889d8762432ef864df107e097d2b19e93c8d808c2e21", "nonce": "8688105887642a3cbb61889d8762432ef864df107e097d2b19e93c8d808c2e21",
"note": "public note", "note": "public note",
"password": {}, "password": {},
"safe_note": {}, "safe_note": {},
...@@ -108,24 +103,27 @@ for more: https://nodejs.org/api/crypto.html#crypto_crypto_createdecipheriv_algo ...@@ -108,24 +103,27 @@ for more: https://nodejs.org/api/crypto.html#crypto_crypto_createdecipheriv_algo
} }
``` ```
#### Entry level encryption ### Entry level encryption
Every entry contains keys from upper example. Every entry contains keys from upper example.
- ```title```: title is represented as string. If given string is matching URL, it will be shown on device as domain without protocol prefix.
- ```username```: string, will be passed to device, in encryption/decryption process - `title`: title is represented as string. If given string is matching URL, it will be shown on device as domain without protocol prefix.
- ```nonce```: hidden generated string which is output of cipherKeyValue over Title + Username key and random values - `username`: string, will be passed to device, in encryption/decryption process
- ```password```: is buffer array output of plain string and nonce (encryption process described later) - `nonce`: hidden generated string which is output of cipherKeyValue over Title + Username key and random values
- ```safe_note```: is also buffer array output of plain string and nonce (also described later) - `password`: is buffer array output of plain string and nonce (encryption process described later)
- ```note```: is plain UTF8 string - `safe_note`: is also buffer array output of plain string and nonce (also described later)
- ```tags```: is array of Tags key values - `note`: is plain UTF8 string
- `tags`: is array of Tags key values
Step by step entry encryption: Step by step entry encryption:
1. Generate random 32 bytes buffer and convert to HEX string inadequately called ```nonce```
2. Set key as ```'Unlock ' + title + ' for user ' + username + '?'```
3. Ask device for ```cipherKeyValue```, where path is the same as in the deriving file name, key is described in second step and enc_value is our ```nonce``` from the first step. Do not forget to setup properly other three bool values!
EXAMPLE: 1. Generate random 32 bytes buffer and convert to HEX string inadequately called `nonce`
```javascript 2. Set key as `'Unlock ' + title + ' for user ' + username + '?'`
3. Ask device for `cipherKeyValue`, where path is the same as in the deriving file name, key is described in second step and enc_value is our `nonce` from the first step. Do not forget to setup properly other three bool values!
EXAMPLE:
``` javascript
session.cipherKeyValue( session.cipherKeyValue(
[(10016 | 0x80000000) >>> 0, 0], // same path [(10016 | 0x80000000) >>> 0, 0], // same path
'Unlock github.com for user Satoshi Nakamoto?', 'Unlock github.com for user Satoshi Nakamoto?',
...@@ -135,14 +133,16 @@ false, //askOnEncrypt? is the same in encryption and decryption ...@@ -135,14 +133,16 @@ false, //askOnEncrypt? is the same in encryption and decryption
true) // askOnDecrypt? we want this becuase otherwise somebody could rob us! true) // askOnDecrypt? we want this becuase otherwise somebody could rob us!
``` ```
4. Then we use our famous ```nonce``` from the first step in ```AES-256-GCM``` algorithm encryption for ```password``` string and ```safe_note``` string. Process of encryption is the same as in the deriving encryption key and file level encryption. So basically we get some Buffer array output with 12 bytes of IV and 16 bytes of GCM authTag and the rest is cipherText. 4. Then we use our famous `nonce` from the first step in `AES-256-GCM` algorithm encryption for `password` string and `safe_note` string. Process of encryption is the same as in the deriving encryption key and file level encryption. So basically we get some Buffer array output with 12 bytes of IV and 16 bytes of GCM authTag and the rest is cipherText.
5. Output of each encryption is stored to appropriate keys, just instead of generated ```nonce``` we store result from third step ( ```cipherKeyValue ```) which we later use for decryption process 5. Output of each encryption is stored to appropriate keys, just instead of generated `nonce` we store result from third step ( `cipherKeyValue`) which we later use for decryption process
### Entry decryption
Entry decryption: 1. We ask device for the same `cipherKeyValue` as in encryption process, just instead of `nonce`, we use our encrypted result and boolean value `encrypt?` is **false**!
1. We ask device for the same ```cipherKeyValue ``` as in encryption process, just instead of ```nonce```, we use our encrypted result and boolean value ```encrypt? ``` is **false**!
EXAMPLE: EXAMPLE:
```javascript
``` javascript
session.cipherKeyValue( session.cipherKeyValue(
[(10016 | 0x80000000) >>> 0, 0], // same path [(10016 | 0x80000000) >>> 0, 0], // same path
'Unlock github.com for user Satoshi Nakamoto?', 'Unlock github.com for user Satoshi Nakamoto?',
...@@ -151,8 +151,5 @@ false, //encrypt? - has to be FALSE in decryption ...@@ -151,8 +151,5 @@ false, //encrypt? - has to be FALSE in decryption
false, //askOnEncrypt? is the same in encryption and decryption false, //askOnEncrypt? is the same in encryption and decryption
true) // askOnDecrypt? we want this becuase otherwise somebody could rob us! true) // askOnDecrypt? we want this becuase otherwise somebody could rob us!
``` ```
2. Other steps are the same as in entry encryption, we just symetrically decrypt values of ```password``` and ```safe_note``` via ```AES-256-GCM``` algorithm. Size of IV and authTag for AES is the same as in encryption. Beware on cipher Key data type - it must be hex. Output is in JSON.
2. Other steps are the same as in entry encryption, we just symetrically decrypt values of `password` and `safe_note` via `AES-256-GCM` algorithm. Size of IV and authTag for AES is the same as in encryption. Beware on cipher Key data type - it must be hex. Output is in JSON.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment