Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • documents/rfcs
  • matograine/rfcs
  • 1000i100/rfcs
  • LukeMarlin/rfcs
  • tuxmain/rfcs
  • pokapow/rfcs
6 results
Select Git revision
Loading items
Show changes
Commits on Source (29)
......@@ -13,6 +13,8 @@ All documents should be implementation agnostic, as specific documentations shou
### Approved RFCs
* RFC_0013: [Duniter Encrypted Wallet Import Format](rfc/0013_Duniter_Encrypted_Wallet_Import_Format.md)
#### DUniter Blockchain Protocol (DUBP)
* V11: [RFC 0009](rfc/0009_Duniter_Blockchain_Protocol_V11.md)
......@@ -26,9 +28,9 @@ All documents should be implementation agnostic, as specific documentations shou
* RFC_0007: [Duniter Ascii Armor Messages](https://git.duniter.org/documents/rfcs/blob/ascii_armor_messages/rfc/0007%20Ascii%20Armor%20Messages.md)
* RFC_0008: [Duniter Messages Encryption and Signature](https://git.duniter.org/documents/rfcs/blob/messages_encryption_and_signature/rfc/0008%20Messages%20Encryption%20and%20Signature.md)
* RFC_0013: [Duniter Encrypted Wallet Import Format](https://git.duniter.org/documents/rfcs/blob/dewif/rfc/0013_Duniter_Encrypted_Wallet_Import_Format.md)
* RFC_0014: [DUBP Mnemonic](https://git.duniter.org/documents/rfcs/blob/dubp-mnemonic/rfc/0014_Dubp_Mnemonic.md)
* RFC_0016: [Checksum for Duniter public keys](rfc/0016_public_key_checksum.md)
* RFC_0017: [Encrypt tx commnent](https://git.duniter.org/documents/rfcs/blob/tx_comment_encrypt/rfc/0017_transaction_comment_encryption.md)
### Drafts RFCs
......
# RFC 13: Duniter Encrypted Wallet Import Format
```txt
RFC: 13
Title: Duniter Encrypted Wallet Import Format
Type: Format
Status: WIP
Author: elois <c@elo.tf>
Created: 2020-02-13
Last edited: 2020-02-13
License: CC-SA
```
## Introduction
A wallet is a pair of asymmetric keys (a public key + a private key).
The purpose of this RFC is to define a standard, inter-operable and secure format for any [DUBP] wallet.
This RFC does not define a file format, it is agnostic of the way the wallet is stored on the disk.
## conventions
* `||` means binary concatenation.
* All string must be encoded in UTF-8 with [NFKD normalization].
## DUBP
[DUBP] only deals with public keys and signatures.
A public key is always paired with a private key, which DUBP will never deal with.
Today DUBP manage only the algorithm ED25519, but in the future DUBP can evolve to manage multiples digital signature algorithms.
So currently a public key for DUBP is to be understood as an Ed25519 public key.
## DEWIF format
DEWIF is an inter-operable and secure format for any DUBP wallet.
DEWIF format is a sequence of bytes whose structure is defined below. It can be used as raw binary data where suitable.
To use the binary data in a text context (email, ftp text transfer, json, html, etc) it is recommended to encode the binary data in a Base64 string. The Base64 string is used here to check the binary data validity.
## Dewif bytes structure
| Version | Currency code | Data expected for this specific version |
|:-------:|:-------------:|:---------------------------------------:|
| 4 bytes | 4 bytes | Any bytes |
## Version
The 4 bytes of the version field must be interpreted as an unsigned integer encoded in big endian.
## Currencies code
| Currency | Code |
|:---------|:-----------|
| None | 0x00000000 |
| Ğ1 | 0x00000001 |
| Ğ1-Test | 0x10000001 |
## Data expected for this specific version
### Version 1
| log N | Algorithm | Nonce | Encrypted data |
|:---------:|:-----------:|:--------:|:----------------:|
| 1 byte | 1 byte | 12 bytes | Any bytes |
#### Algorithm
| Algorithm | Code |
|:----------------|:-----|
| [Ed25519] | 0x00 |
| [BIP32-Ed25519] | 0x01 |
| Unknown* | 0x02 |
*\* Future algorithms can be added to DEWIF v1.*
#### Nonce
The nonce is used to vary the encryption key (see next section).
It must be randomly generated at the creation of the DEWIF.
#### Encrypted data
**Symmetric encryption algorithm:** [XOR cipher]
[XOR cipher] is the fastest symmetric encryption algorithm in the world, the only limitation is that the encryption key must be at least as long as the encrypted data.
**XOR key** = scrypt of user passphrase with the following parameters:
| Parameter | Value |
|:--------------:|:--------------------------------------------:|
|**Password:** | passphrase |
|**Salt** | sha256(`"dewif" \|\| nonce \|\| passphrase`) |
|**N** | `2^(log N)` |
|**r** | 16 |
|**p** | 1 |
|**dkLen** | Encrypted data length |
##### Algorithm Ed25519
| Seed | Public key |
|:-------------:|:-------------:|
| 32 bytes | 32 bytes |
The public key serves as a checksum. To check that the DEWIF base64 string is not corrupted, simply generate a keypair with the seed and check that the obtained public key matches.
**Example 1:**
| Parameter | Value |
|:-----------------:|:----------------------------:|
|**Log N** | 12 |
|**Algorithm** | Ed25519 |
|**Keypair seed** | 0xbfa3f6e322cf21d0e652f79a69df9498fdf5347665e5646d9041f756496a1143 |
```txt
0x000000001 #v1
0x100000001 #g1-test
0x0C # log N
0x00 # Algorithm Ed25519
0x013194f1286512cf094295cb # nonce
0xbfa3f6e322cf21d0e652f79a69df9498fdf5347665e5646d9041f756496a1143 # keypair seed
0x17df9d2b059cdd2825955691e3a783e6da403148ddebb1144d1a9b9e545f2371 # public key
```
**XOR key generated from scrypt with the following parameters:**
| Parameter | Value |
|:-----------------:|:-------------:|
| **N** | `2^12 = 4096` |
| **r** | 16 |
| **p** | 1 |
| **dkLen** | 64 |
DEWIF base 64 string (with xor key `"toto titi tata"`):
`AAAAARAAAAEMAAExlPEoZRLPCUKVy0iKnn1HUSFcmhwJPQETAghFDvH8ZmX59IuvR9hYV1gnVjCpU+TGOdUzyQmj3+auw3vUpFQYBiRlh67/I1xAhZM=`
##### Algorithm Bip32-Ed25519
| Language code | Entropy length | Mnemonic entropy | Checksum |
|:--------------:|:--------------:|:----------------:|:--------:|
| Uint8 (1 byte) | Uint8 (1 byte) | 32 bytes | 8 bytes |
Language code:
| Language code | Language |
|:--------------:|:-------------------:|
| 0 | English |
| 1 | Chinese simplified |
| 2 | Chinese traditional |
| 3 | French |
| 4 | Italian |
| 5 | Japanese |
| 6 | Korean |
| 7 | Spanish |
Mnemonic entropy is defined on [BIP39].
The entropy is stored in 32 bytes to avoid revealing the size of the stored mnemonic.
If the entropy of the mnemonic is less than 32 bytes, the extra bytes are ignored (they can have any value).
To check that the DEWIF base64 string is not corrupted, compute the hash sha256 of `Nonce || Language code || Entropy length || Mnemonic entropy`. The first eight bytes of the sha256 hash constitute the checksum.
WARNING: Only the "useful" part of the entropy is used to calculate the checksum, the extra bytes are ignored.
**Example 2:**
| parameter | value |
|:-----------------:|:----------------------------:|
| **Log N** | 14 |
| **Algorithm** | Bip32-Ed25519 |
| **mnemonic** | `"crop cash unable insane eight faith inflict route frame loud box vibrant"` |
```txt
0x000000001 #v1
0x100000001 #g1-test
0x0F # log N
0x01 # Algorithm Bip32-Ed25519
0xc54299ae71fe2a4ecdc7d58a # nonce
0x00 # Language english
0x10 # Entropy length
0x33E46BB13A746EA41CDDE45C90846A79 # Mnemonic entropy
0xaa083bd16c8317121d34b5aed1c1420a # Mnemonic entropy padding (random bytes)
0x8a2bb5a0cb0acfba # checksum (SHA256 of 0xc54299ae71fe2a4ecdc7d58a || 0x00 || 0x10 || 0x33E46BB13A746EA41CDDE45C90846A79)
```
**XOR key generated from scrypt with the following parameters:**
| Parameter | Value |
|:--------------:|:--------------:|
| **N** | `2^14 = 16384` |
| **r** | 16 |
| **p** | 1 |
| **dkLen** | 42 |
DEWIF base 64 string (with xor key `"toto titi tata"`):
`AAAAARAAAAEOAcVCma5x/ipOzcfViufNdfj5k4Sl5zdrHLf9PPGDkH1Pz3y8tFrx/jZZcJd92LIk+EWIrjxiSw==`
[BIP32-Ed25519]: https://drive.google.com/file/d/0ByMtMw2hul0EMFJuNnZORDR2NDA/view
[BIP39]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#generating-the-mnemonic
[DUBP]: https://git.duniter.org/nodes/common/doc/blob/master/rfc/0010_Duniter_Blockchain_Protocol_V12.md
[Ed25519]: https://tools.ietf.org/html/rfc8032
[NFKD normalization]: https://unicode.org/reports/tr15/#Norm_Forms
[XOR cipher]: https://en.wikipedia.org/wiki/XOR_cipher
......@@ -15,6 +15,7 @@ License: AGPL-3
This document proposes an enhancement on Tortue's standard for public key checksum:
https://github.com/Tortue95/Duniter_Paper_Wallet/blob/master/Duniter_Auth_Protocol.md
For compatibility, clients MAY accept checksum based on this last standard for user inputs.
## Public key format
......@@ -33,14 +34,25 @@ Example of two valid public keys referring to the same Ed25519 binary public ke
```
When converting a public key to its binary representation, the length of the bytes array MUST be verified.
If the length of the array is inferior to 32, zero-bytes MUST be prepended.
- If the length of the array is inferior to 32, zero-bytes MUST be prepended.
- If the length of the array is superior to 32, leading zero-bytes MUST be removed.
- If there is one leading non-zero byte and length is superior to 32, then the public key is not valid.
```python
# convert public key string to bytes
pubkey_byte = bytearray(base58.b58decode(pubkey))
# prepend zero-bytes until the public key is 32 bytes long
while len(pubkey_byte) < 32:
pubkey_byte = bytearray(b"\x00") + pubkey_byte
# remove leading zero-bytes if length is superior to 32
while len(pubkey_byte) > 32:
if pubkey_byte[0] == 0:
del pubkey_byte[0]
# raise error if leading byte is not null
else:
raise ValueError("Invalid public key: bytes length is too long")
```
## Checksum display
......@@ -51,8 +63,8 @@ It is displayed after the public key, separated by a colon `:`.
Example of two valid representations of a public key with their checksum:
```
12BjyvjoAf5qik7R8TKDJAHJugsX23YgJGi2LmBUv2nx:8pQ
2BjyvjoAf5qik7R8TKDJAHJugsX23YgJGi2LmBUv2nx:8pQ
12BjyvjoAf5qik7R8TKDJAHJugsX23YgJGi2LmBUv2nx:8BD
2BjyvjoAf5qik7R8TKDJAHJugsX23YgJGi2LmBUv2nx:8BD
```
This function is used when a public key is typed manually on the keyboard (or issue on QRcode reader)
......@@ -76,8 +88,8 @@ This short form consists in:
Example of short-form public keys with checksum:
```
12Bj…v2nx:8pQ
2Bjy…v2nx:8pQ
12Bj…v2nx:8BD
2Bjy…v2nx:8BD
```
Short form CAN be used for user input, only in research fields.
......@@ -92,17 +104,14 @@ In that case, the same color MUST be used for the separating colon.
To compute the checksum:
0) use the binary representation of the public key :
for simplification we use a pubkey that is 32 bits long once decoded.
`pubkey = bytearray(base58.b58decode("J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX"))`
1) `sha256(pubkey)`
`0x47c7aee49dfb9bea99949d04623281d8ad6188be8f6a698b0eb5994fa44d0a67`
2) `sha256(sha256(pubkey))`
`0x04a7ad22fbe357fbf5f58b2996fe5840fa2f977b9f6aa4c62575e68f75882672`
3) `Base58.encode(sha256(sha256(pubkey))`
`KAvdGW7rpV68WDQPVN2TCrCoyvAHqMK1nSTS8y68bmB`
4) We only take the 3 first characters of this value to get the checksum
`KAv`
2) `Base58.encode(sha256(pubkey))`
`5qCYkJMWgNA54gZz4HMQLbxL5btDmTS3EuHHCTcJaqGi`
3) We only take the 3 first characters of this value to get the checksum
`5qC`