Commit be0b1a1e authored by Karel Bílek's avatar Karel Bílek Committed by Karel Bilek

Writing SLIP-0012

parent 31bc3622
...@@ -7,23 +7,107 @@ Type: Standard ...@@ -7,23 +7,107 @@ Type: Standard
Status: Draft Status: Draft
Authors: Pavol Rusnak <stick@satoshilabs.com> Authors: Pavol Rusnak <stick@satoshilabs.com>
Marek Palatinus <slush@satoshilabs.com> Marek Palatinus <slush@satoshilabs.com>
Karel Bilek <kb@karelbilek.com>
Created: 2014-06-12 Created: 2014-06-12
``` ```
##Abstract ##Abstract
This is a section for an abstract. This document is explaining symmetric encryption on hardware devices, using deterministic hierarchy.
##Motivation ##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 ##Body
This is a section for a body. The title of the section should be changed ### Overview
and the section can be split into multiple sections and subsections.
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.
##References ##References
This is a section for references such as links to other documents (BIP or SLIP) 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`).
or to reference implementations.
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