Skip to content
Snippets Groups Projects
Select Git revision
  • tx_comment_encrypt
  • master default
  • 0019-secret-ballot-voting
  • feature/protocol-v2s
  • 0016_checksum
  • dubp_v13
  • hd_wallet
  • dubp-mnemonic
  • ws2p_v2
  • dubp_v12
  • tx-out-hash
11 results

0017_transaction_comment_encryption.md

Blame
  • RFC 17: Transaction Comment Encryption

    This RFC defines a format for encrypting transaction comments for the case of transactions involving a single issuer key and a single receiver key.

    Let Si the seed of the issuer and Pi its associated ed25519 public key. Let Sr the seed of the receiver and Pr its associated ed25519 public key.

    Convert Ed25519 keys to x25519 keys

    The first step is to convert the Ed25519 keys into x25519 keys (also called curve25519 keys).

    Convert Ed25519 secret key to x25519 secret key

    Use the first 32 bytes of the extended secret key.

    The extended secret key is derived from the seed by the NaCl function crypto_box_seed_keypair.

    Let Si' = crypto_box_seed_keypair(Si)[..32];

    Convert Ed25519 public key to x25519 public key

    Use NaCl function crypto_sign_ed25519_pk_to_curve25519.

    Let Pr' = crypto_sign_ed25519_pk_to_curve25519(Pr)

    Generate symmetric encryption key

    We use nacl function crypto_box_beforenm. Then use scrypt with a random nonce.

    Let R = crypto_box_beforenm(Si', Pr') = crypto_box_beforenm(Sr', Pi').

    Let s be a random salt of 16 bytes.

    The symmetric encryption key k is obtained as follows:

    k = scrypt(R, s)

    With following parameters for scrypt:

    Parameter Value
    password R
    Salt s
    N 1024
    r 8
    p 1
    dkLen message length

    Encrypt with XOR cipher

    Encrypt bit per bit with XOR cipher.

    Serialize encrypted message with meta data

    Metadata Encrypted Data
    20 bytes max. 171 bytes

    Metadata

    Magic value Version Message type Nonce
    0x27b6 0x01 1 byte 16 bytes

    Encrypted Data

    Real message length UTF8 message Random extra bytes
    1 byte Any byte Any bytes

    The message must be encoded in UTF8.

    Magic value

    A constant value that recognizes that the data should be interpreted according to this format.

    A possible future format must use a different magic value.

    Version

    Future versions of the present format must increment this byte.

    Message type

    Code Significance
    0x00 For a human
    0x01 For a machine

    Nonce

    An sequence of 16 random bytes to use as scrypt salt

    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 (without padding) 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.

    Quickly recognize if a comment fits this format

    You can quickly recognize if a comment fits this format with the following regex: J7YB[0-9a-zA-Z+/]{24,}

    Encrypt transaction comment (Issuer side)

    Let m the user message bytes encoded in UTF8. Let t the message type.

    1. Generate 16 random bytes and stores them in a byte array nonce.
    2. Compute l = m.lenght
    3. Generate a random integer x between 0 and 170 - l
    4. Generate x random bytes and add them at end of m.
    5. compute L = l + x + 1
    6. compute Si' and Pr'.
    7. Create a bytes array dataToEncrypt of length L
    8. Push the byte l in dataToEncrypt
    9. Append m to dataToEncrypt
    10. Compute R = crypto_box_beforenm(Si', Pr')
    11. Generate symmetric encryption key k = scrypt(R, salt: nonce, N: 1024, r: 8, p: 1, dkLen: L)
    12. compute encryptedData = dataToEncrypt ^ k
    13. Create a bytes array b of length L + 20
    14. Fill the three first bytes of b with content 0x27b601
    15. Push the byte t in b
    16. Append nonce to b
    17. Append encryptedData to b
    18. Compute source = base64.encode(b)
    19. Write source in a comment field of transaction 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)
    2. Ensure that b.length >= 3
    3. Ensure that b[0] = 0x27 and b[1] = 0xb6 (magic value check)
    4. Ensure that b[2] = 0x01 (version check)
    5. Read t = b[3]. Depending on the t value and your reading context, you can stop here or continue.
    6. Ensure that b.length >= 21
    7. compute Sr' and Pi'.
    8. Compute R = crypto_box_beforenm(Sr', Pi')
    9. compute L = b.length - 20
    10. Read nonce: the bytes array from b[4] to b[19]
    11. Generate symmetric encryption key k = scrypt(R, salt: nonce, N: 1024, r: 8, p: 1, dkLen: L)
    12. Read encryptedMessage: the bytes array from b[20] to b[b.length -1]
    13. Compute m = encryptedMessage ^ k
    14. Read l = m[0]
    15. Ensure that m.length > l
    16. Interpret bytes m[1] to m[l] as an UTF8 string

    Example

    Parameter Value
    Sender Public Key EVfy1VoZwbuN7L69kYiHxeosJLh5azkHV8G6TaSLy94r
    Sender Seed 0x0c6a15d0004d24a40f6503300d4971032fb057ff7dc229d651683b413c96a216
    Receiver Public Key 8txjWNFZhMJbKPijvnFybeksN1QpKaKJrM4jW8HhnFsX
    Receiver Seed 0x214955b558c7793268589e557eda2ab69b5293b73d3907f82c82e12d69c47221
    Comment My taylor is rich ? Isn't it ? Un été 42...
    Nonce 0x16740285721adeb10da04106c9eb9e34
    Extra Bytes 0x17968f2f344679fe23ef483a53adcaa18ecd753036dd2cdab1
    Scrypt Password 0xe63c31edb6e9e4fa04142cd73f30423aa7fb09e404fb60f154dcc913a7e3657c
    XOR Key 0x691114edf5f3da4f4c04b77842da44a4fa97cd59fee742c98244441897e91532de8bcf883d279d4cf4ab3715014cf417a309c979ee4058613668698e1f0df8edf4ac556868e64f
    Encrypted comment J7YBABZ0AoVyGt6xDaBBBsnrnjREXG3NgZKjIyN2lxEx+jbNmf/tZt6uMaelMGRx48kqEovl70uUU17l1J8FOy9i44EsJv0/l757jn5SOiPVrHYggZxjtUQ8/g