Crate nettext

source ·
Expand description

A text-based data format for cryptographic network protocols.

use nettext::enc::*;
use nettext::dec::*;
use nettext::crypto::*;

let final_payload = {
    let keypair = SigningKeyPair::gen_with_defaults();

    // Encode a fist object that represents a payload that will be hashed and signed
    let signed_payload = list([
        string("CALL").unwrap(),
        string("myfunction").unwrap(),
        dict([
            ("a", string("hello").unwrap()),
            ("b", string("world").unwrap()),
            ("c", raw(b"{ a = 12, b = 42 }").unwrap()),
            ("d", bytes_split(&((0..128u8).collect::<Vec<_>>()))),
        ]).unwrap(),
        keypair.public_key.term().unwrap(),
    ]).unwrap().encode();
    eprintln!("{}", std::str::from_utf8(&signed_payload).unwrap());

    let hash = compute_hash(&signed_payload, None);
    let sign = compute_signature(&signed_payload[..], &keypair.secret_key);

    // Encode a second object that represents the signed and hashed payload
    dict([
        ("hash", hash.term().unwrap()),
        ("signature", sign.term().unwrap()),
        ("payload", raw(&signed_payload).unwrap()),
    ]).unwrap().encode()
};
eprintln!("{}", std::str::from_utf8(&final_payload).unwrap());

// Decode and check everything is fine
let signed_object = decode(&final_payload).unwrap();
let [hash, signature, payload] = signed_object.dict_of(["hash", "signature", "payload"], false).unwrap();
let hash = hash.hash().unwrap();
let signature = signature.signature().unwrap();
let expected_hash = compute_hash(payload.raw(), None);
assert_eq!(hash, expected_hash);

let object2 = decode(payload.raw()).unwrap();

let [verb, arg1, arg2, pubkey] = object2.list_of().unwrap();
let pubkey = pubkey.public_key().unwrap();
assert!(verify_signature(&signature, payload.raw(), &pubkey));

assert_eq!(verb.string().unwrap(), "CALL");
assert_eq!(arg1.string().unwrap(), "myfunction");

The value of text1 would be as follows:


CALL myfunction {
    a = hello,
    b = world,
    c = { a = 12, b = 42 },
    d = AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4v
      MDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5f
      YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn8,
  } M3_to5OQ5TvIVyoRXTSK4Jz-zvSqsuh3a68haud_8Vs

And the value of text2 would be as follows:

{
  hash = Hxpas10VnFIq8WIWGmQk7YLbxT-OMIkg0-sKSBJnUuo,
  payload = CALL myfunction {
    a = hello,
    b = world,
    c = { a = 12, b = 42 },
    d = AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4v
      MDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5f
      YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn8,
  } M3_to5OQ5TvIVyoRXTSK4Jz-zvSqsuh3a68haud_8Vs,
  signature = DAgQDqxi6rDEkGVoUmfHexWUCFYKNbQR0Fgp3_EiaMxiFLeQdy3w3If_lsYqDDmWHYR51whfaNGQZ6PxVthMAA,
}

Note that the value of text1 is embedded as-is inside text2. This is what allows us to check the hash and the signature: the raw representation of the term hasn’t changed.

Modules

Helpers to use cryptographic data types in nettext
Functions to decode nettext and helpers to map it to data structures
Functions to generate nettext representations of data structures
Serde serialization and deserialization for nettext