Commit b5b0b66e authored by Éloïs's avatar Éloïs
Browse files

[RFC17] full rework: hide message length + add magic value + add version

parent 62a7e3a4
......@@ -52,50 +52,92 @@ Encrypt bit per bit with XOR cipher.
## Serialize encrypted message with meta data
| Prefix | Message type | Message length | Salt | Encrypted UTF8 message |
|:-------:|:------------:|:--------------:|:--------:|:-----------------------:|
| 2 bytes | 1 byte | 1 byte | 16 bytes | Any bytes |
The maximum length of a message is 169 bytes.
| Magic value | Version | Message type | Salt | Real message length | Encrypted UTF8 message | Random extra bytes |
|:-----------:|:-------:|:------------:|:--------:|:-------------------:|:----------------------:|:------------------:|
| `0x27b6` | `0x01` | 1 byte | 16 bytes | 1 byte (encrypted) | Any bytes | Any bytes |
The message must be encoded in UTF8.
### Prefix
### Magic value
A constant value that recognizes that the data should be interpreted according to this format.
A constant value that indicates the type of format. For the present format defined in this RFC, the prefix is `0x0100`.
A possible future format must use a different magic value.
Future version of the present format must increment second byte (next version use prefix `0x0101`).
### Version
A possible future format should increment the first byte of the prefix.
Future versions of the present format must increment this byte.
### Message type
| Code | Significance |
|:----:|:--------------------------------:|
| 0x00 | Write by a human for a human |
| 0x01 | Write by a human for a machine |
| 0x10 | Write by a machine for a human |
| 0x11 | Write by a machine for a machine |
| Code | Significance |
|:----:|:---------------:|
| 0x00 | For a human |
| 0x01 | For a machine |
### Real message length
Indicates the real size of the message in bytes. That is, the number of bytes that should be interpreted as an UTF8 string. There may be extra bytes, the extra bytes should be ignored (see section "Random extra bytes").
### Random extra bytes
The presence of extra bytes only serves to hide the real length of the message from outside observers.
There may well be no extra bytes, just as there may be many.
It is recommended to randomly generate a random number of extra bytes to obscure the real length of the message.
## Encoding in transaction document
Encrypted message in encoded in base 64 in transaction comment directly (DUBP protocol already accept all base 64 characters).
## Maximum message length
The DUBP protocol allows up to 255 characters in the comment field, so it is possible to encode up to 191 bytes in base64 (without padding).
There are at least 21 bytes of metadata, so the maximum size of a message is **170 bytes**.
## Encrypt transaction comment (Issuer side)
Let `m` the user message bytes encoded in UTF8.
Let `t` the message type.
1. Generate 12 random bytes a stores them in a byte array `nonce`.
1. Compute `l = m.lenght`
1. Generate a random integer `x` between `0` and `170 - l`
1. Generate `x` random bytes and add them at end of `m`.
1. compute `L = l + x`
1. compute `Si'` and `Pr'`.
1. Compute `R = crypto_box_beforenm(Si', Pr')`
1. Generate symmetric encryption key `k = scrypt(R, salt, N: 1024, r: 12, p: 1, dkLen: L)`
1. compute `encryptedMessage = m ^ k`
1. Create a bytes array `b` of length `L + 20`
1. Fill the three first bytes of `b` with content `0x27b601`
1. Push the byte `t` in `b`
1. Append `nonce` to `b`
1. Push the byte `l` in `b`
1. Append `m` to `b`
1. Compute `source = base64.encode(b)`
1. Write `source` in a comment field of trasaction document
## Decrypt transaction comment (Receiver side)
Let `source` a base64 string read from comment field of a transaction document.
1. compute `b = base64.decode(source)`
1. Ensure that `b.length >= 3`
1. Ensure that `b[0] = 0x27` and `b[1] = 0xb6` (magic value check)
1. Ensure that `b[2] = 0x01` (version check)
1. Read `t = b[3]`. Depending on the `t` value and your reading context, you can stop here or continue.
1. Ensure that `b.length >= 21`
1. compute `Sr'` and `Pi'`.
2. Compute `R = crypto_box_beforenm(Sr', Pi')`
3. Read meta data `l = Message length`
4. Read meta data `s = Salt`
5. Generate symetric encryption key `k = scrypt(R, s, N: 1024, r: 12, p: 1, dkLen: l)`
6. compute `m = encryptedMessage ^ k`
7. Interpret `m` as an UTF8 string
## Hide the real length of the message
It is possible to encode a message that is intentionally longer than the real message in order to not reveal the size of the message.
In this case, it is usual to put a [Null character] at the end of the message to know where the real end of the message is.
The characters after the [Null character] should not be displayed, but they should remain valid UTF8 characters.
1. Compute `R = crypto_box_beforenm(Sr', Pi')`
1. compute `L = b.length - 20`
1. Let `salt` a bytes array from `b[4]` to `b[19]`
1. Generate symmetric encryption key `k = scrypt(R, salt, N: 1024, r: 12, p: 1, dkLen: L)`
1. Let `encryptedMessage` a bytes array from `b[20]` to `b[b.length -1]`
1. compute `m = encryptedMessage ^ k`
1. Read `l = m[0]`
1. Ensure that `m.length > l`
1. Interpret bytes `m[1]` to `m[l]` as an UTF8 string
[crypto_box_beforenm]: https://nacl.cr.yp.to/box.html
[Null character]: https://en.wikipedia.org/wiki/Null_character
......
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