swap slip-0011 and slip-0012

parent be0b1a1e
......@@ -7,23 +7,110 @@ Type: Standard
Status: Draft
Authors: Pavol Rusnak <stick@satoshilabs.com>
Marek Palatinus <slush@satoshilabs.com>
Karel Bilek <kb@karelbilek.com>
Created: 2014-06-12
```
##Abstract
This is a section for an abstract.
This document is explaining symmetric encryption on hardware devices, using deterministic hierarchy.
##Motivation
This is a section for a motivation.
We want to provide a symmetric encryption in the hardware wallet, where the key doesn't exit the device, and where the user might be forced to confirm the encryption/decryption on the display.
##Body
This is a section for a body. The title of the section should be changed
and the section can be split into multiple sections and subsections.
###Overview
The following data are sent to the hardware wallet:
* BIP 32 path
* key (that is being shown on the device)
* value
* encrypt/decrypt direction
* should user confirm on encrypt?
* should user confirm on decrypt?
* optional IV
Value is what is actually being encrypted. The key for the encryption is constructed from the private key on the BIP address, the key displayed on the device, and the two informations about whether to ask for confirmation.
It is constructed in such a way, that different path, key or the confirm information will get a different encryption key and IV. So, you cannot "skip" the confirmation by using different input.
IV can be either manually set, or it is computed together with the key.
###Details
The details are best explained on a slightly simplified code from TREZOR Python emulator.
````python
def _cipher_keyvalue(self, address_n, key, value, encrypt, ask_on_encrypt, ask_on_decrypt, iv):
if len(value) % 16 > 0:
return Failure(message="Input length must be a multiple of 16")
private_key = BIP32(self.storage.get_node()).get_private_node(list(address_n)).private_key
key += "E1" if ask_on_encrypt else "E0"
key += "D1" if ask_on_decrypt else "D0"
secret = hmac.HMAC(key=private_key, msg=key, digestmod=hashlib.sha512).digest()
aes_key = secret[0:32]
aes_iv = iv if iv else secret[32:48]
aes = pyaes.AESModeOfOperationCBC(key=aes_key, iv=aes_iv)
if encrypt:
res = ''.join([aes.encrypt(value[i:i+16]) for i in range(0, len(value), 16)])
else:
res = ''.join([aes.decrypt(value[i:i+16]) for i in range(0, len(value), 16)])
return CipheredKeyValue(value=res)
````
````python
if len(value) % 16 > 0:
return Failure(message="Input length must be a multiple of 16")
````
First, the value is checked, if it is divisable into 16-byte blocks, since the symmetric cipher is block cipher. The application has to pad the blocks itself and ensure safety; for example, by using PKCS7.
````python
private_key = BIP32(self.storage.get_node()).get_private_node(list(address_n)).private_key
````
Private key of the BIP32 node is derived.
````python
key += "E1" if ask_on_encrypt else "E0"
key += "D1" if ask_on_decrypt else "D0"
````
The key, displayed on the device, is concatenated with either E1 or E0 and either D1 or D0, depending on whether the confirmation is enabled in a given direction.
````python
secret = hmac.HMAC(key=private_key, msg=key, digestmod=hashlib.sha512).digest()
````
The key, with the concatenated E1/E0 or D1/D0, is HMACed, with the private key from HD Node, with SHA512 as a hash function.
````python
aes_key = secret[0:32]
aes_iv = iv if iv else secret[32:48]
````
The AES key is the first 32 bytes of the HMAC; the input vector is the next 16 bytes.
````python
aes = pyaes.AESModeOfOperationCBC(key=aes_key, iv=aes_iv)
````
The algorithm is AES, in CBC mode.
````python
if encrypt:
res = ''.join([aes.encrypt(value[i:i+16]) for i in range(0, len(value), 16)])
else:
res = ''.join([aes.decrypt(value[i:i+16]) for i in range(0, len(value), 16)])
````
The result are the encrypted/decrypted blocks, concatenated together.
##References
This is a section for references such as links to other documents (BIP or SLIP)
or to reference implementations.
The algorithm is implemented in [TREZOR firmware](https://github.com/trezor/trezor-mcu/blob/master/firmware/fsm.c) (function `fsm_msgCipherKeyValue`) and its [emulator](https://github.com/trezor/trezor-emu/blob/master/trezor/machine.py#L781) (function `_cipher_keyvalue`).
It is used in algorithms described in [SLIP-0015](slip-0015.md) and [SLIP-0016](slip-0016.md).
......@@ -7,107 +7,23 @@ Type: Standard
Status: Draft
Authors: Pavol Rusnak <stick@satoshilabs.com>
Marek Palatinus <slush@satoshilabs.com>
Karel Bilek <kb@karelbilek.com>
Created: 2014-06-12
```
##Abstract
This document is explaining symmetric encryption on hardware devices, using deterministic hierarchy.
This is a section for an abstract.
##Motivation
We want to provide a symmetric encryption in the hardware wallet, where the key doesn't exit the device, and where the user might be forced to confirm the encryption/decryption on the display.
This is a section for a motivation.
##Body
### Overview
The following data are sent to the hardware wallet:
* BIP 32 path
* key (that is beging asked on the device)
* value
* encrypt/decrypt direction
* should user confirm on encrypt?
* should user confirm on decrypt?
* optional IV
Value is what is actually being encrypted. The key for the encryption is constructed from the private key on the BIP address, the key displayed on the device, and the two informations about whether to ask for confirmation.
It is constructed in such a way, that different path, key or the confirm information will get a different encryption key and IV. So, you cannot "skip" the confirmation by using different input.
IV can be either manually set, or it is computed together with the key.
### Details
The details are best explained on a slightly simplified code from TREZOR Python emulator.
````python
def _cipher_keyvalue(self, address_n, key, value, encrypt, ask_on_encrypt, ask_on_decrypt, iv):
if len(value) % 16 > 0:
return Failure(message="Input length must be a multiple of 16")
private_key = BIP32(self.storage.get_node()).get_private_node(list(address_n)).private_key
key += "E1" if ask_on_encrypt else "E0"
key += "D1" if ask_on_decrypt else "D0"
secret = hmac.HMAC(key=private_key, msg=key, digestmod=hashlib.sha512).digest()
aes_key = secret[0:32]
aes_iv = iv if iv else secret[32:48]
aes = pyaes.AESModeOfOperationCBC(key=aes_key, iv=aes_iv)
if encrypt:
res = ''.join([aes.encrypt(value[i:i+16]) for i in range(0, len(value), 16)])
else:
res = ''.join([aes.decrypt(value[i:i+16]) for i in range(0, len(value), 16)])
return CipheredKeyValue(value=res)
````
````python
if len(value) % 16 > 0:
return Failure(message="Input length must be a multiple of 16")
````
First, the value is checked, if it is divisable into 16-byte blocks, since the symmetric cipher is block cipher. The application has to pad the blocks itself and ensure safety; for example, by using PKCS7.
````python
private_key = BIP32(self.storage.get_node()).get_private_node(list(address_n)).private_key
````
Private key of the BIP32 node is derived.
````python
key += "E1" if ask_on_encrypt else "E0"
key += "D1" if ask_on_decrypt else "D0"
````
The key, displayed on the device, is concatenated with either E1 or E0 and either D1 or D0, depending on whether the confirmation is enabled in a given direction.
````python
secret = hmac.HMAC(key=private_key, msg=key, digestmod=hashlib.sha512).digest()
````
The key, with the concatenated E1/E0 or D1/D0, is HMACed, with the private key from HD Node, with SHA512 as a hash function.
````python
aes_key = secret[0:32]
aes_iv = iv if iv else secret[32:48]
````
The AES key is the first 32 bytes of the HMAC; the input vector is the next 16 bytes.
````python
aes = pyaes.AESModeOfOperationCBC(key=aes_key, iv=aes_iv)
````
The algorithm is AES, in CBC mode.
````python
if encrypt:
res = ''.join([aes.encrypt(value[i:i+16]) for i in range(0, len(value), 16)])
else:
res = ''.join([aes.decrypt(value[i:i+16]) for i in range(0, len(value), 16)])
````
The result are the encrypted/decrypted blocks, concatenated together.
This is a section for a body. The title of the section should be changed
and the section can be split into multiple sections and subsections.
##References
The algorithm is implemented in [TREZOR firmware](https://github.com/trezor/trezor-mcu/blob/master/firmware/fsm.c) (function `fsm_msgCipherKeyValue`) and its [emulator](https://github.com/trezor/trezor-emu/blob/master/trezor/machine.py#L781) (function `_cipher_keyvalue`).
This is a section for references such as links to other documents (BIP or SLIP)
or to reference implementations.
......@@ -54,7 +54,7 @@ We first get the master key by sending CipherKeyValue to hardware device with fo
* ask_on_encrypt, ask_on_decrypt: true
* iv: unset
CipherKeyValue will be defined in SLIP-0011; right now you can check the source code in `trezor source code`_.
CipherKeyValue is defined in [SLIP-0011](slip-0011.md).
.. _trezor source code: https://github.com/trezor/trezor-mcu/blob/master/firmware/fsm.c#L451-L483
......
......@@ -43,7 +43,8 @@ session.cipherKeyValue(
'2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee',
true, true, true)
```
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).
CipherKeyValue is defined in [SLIP-0011](slip-0011.md).
### Deriving file name
......
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