0.1.0 • Published 6 months ago

tingl-client-core v0.1.0

Weekly downloads
-
License
MIT
Repository
-
Last release
6 months ago

Client core library

Client core library is a cross-platform SDK containing all required crypto primitives and protocols.

Key management

Generate a new keypair

import { KeyPair } from "client-core";

let keypair = new KeyPair();
console.log(keypair.public.toHexString());
#include <stdio.h>
#include <stdlib.h>
#include "libclient_core.h"

int main(void) {
    KeyPair *keypair = keypair_generate();

    char *keypair_hex = keypair_to_hex_string(keypair);

    printf("Keypair: %s\n", keypair_hex);

    return 0;
}

Create a keypair instance from bytes

import { KeyPair } from "client-core";
let alice_bytes = new KeyPair().toBytes();
let alice = KeyPair.fromBytes(alice_bytes);
    
console.log(alice.toHexString());
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libclient_core.h"

int main(void) {
  KeyPair* keypair = keypair_generate();
  
  uint8_t* bytes = keypair_to_bytes(keypair);
  
  KeyPair* from_bytes = keypair_from_bytes(bytes);
  
  printf("%s", keypair_to_hex_string(from_bytes));
  
  return 0;
}

Generate a new key with mnemonic phrase and optional password

import { KeyPair } from "client-core";

let keypairWithPhrase = KeyPair.generateWithPhrase(12);
let alice = keypairWithPhrase.keypair();
let phrase = keypairWithPhrase.phrase();

console.log(alice.toHexString(), phrase);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "libclient_core.h"

int main(void) {
  KeyPairWithPhrase* keypair_with_phrase = keypair_generate_with_phrase(12);

  printf("%s", keypair_with_phrase->phrase);

  return 0;
}

Restore keypair from mnemonic phrase and optional password.

import { KeyPair } from "client-core";

let keypairWithPhrase = KeyPair.generateWithPhrase(12);
let alice = keypairWithPhrase.keypair();
let phrase = keypairWithPhrase.phrase();
let aliceFromPhrase = KeyPair.FromPhrase(phrase);

console.log(alice.toHexString() === aliceFromPhrase.toHexString());
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "libclient_core.h"

int main(void) {
  KeyPairWithPhrase* keypair_with_phrase = keypair_generate_with_phrase(12);

  printf("%s\n", keypair_to_hex_string(keypair_with_phrase->keypair));

  KeyPair* restored_keypair = keypair_from_phrase(
      keypair_with_phrase->phrase, strlen(keypair_with_phrase->phrase));

  printf("%s", keypair_to_hex_string(restored_keypair));

  return 0;
}

Extended Triple Diffie-Hellman protocol

Extended Triple Diffie-Hellman (X3DH) protocol is a secret exchange protocol.

X3DH round

import { KeyPair, X3dhInMemProtocol, bytesToHex } from "client-core";

// Prepare Alice protocol instance.
let aliceIdentity = new KeyPair();
let alicePrekey = new KeyPair();
let aliceSignature = aliceIdentity.sign(alicePrekey.public);
let aliceProtocol = new X3dhInMemProtocol(aliceIdentity, alicePrekey, aliceSignature);

let onetimeKeypair = new KeyPair();

// Prepare Bob protocol instance.
let bobIdentity = new KeyPair();
let bobPrekey = new KeyPair();
let bobSignature = bobIdentity.sign(bobPrekey.public.toBytes());
let bobProtocol = new X3dhInMemProtocol(bobIdentity.clone(), bobPrekey.clone(), bobSignature, [onetimeKeypair.toBytes()]);

// Prepare Alice initial message for Bob and derive shared secret as Alice.
let aliceMsg = aliceProtocol.prepareInitMsgBundle(
    bobIdentity.public,
    bobPrekey.public,
    bobSignature,
    onetimeKeypair.public);

// Alice initial message. This message should be sent to Bob.
let aliceInitMsg = aliceMsg.initMsg;

// Alice shared secret.
let aliceSk = aliceMsg.sharedSecret;

// Bob gets a message from Alice, verifies it
// derives it's own shared secret.
let bobSk = bobProtocol.deriveSharedSecret(
    aliceInitMsg.senderIdentity,
    aliceInitMsg.senderEphemeralKey,
    aliceInitMsg.receiverOnetimeKey,
    aliceInitMsg.nonce,
    aliceInitMsg.ciphertext);

// Secret equal for Alice and Bob and this secret could be used
// in other protocols.
console.log(bytesToHex(aliceSk.toBytes()), bytesToHex(bobSk.toBytes()));

Double Ratchet protocol

Double Ratchet protocol is a secure end-to-end encrypted messanging protocol.

Double Ratchet communication

import { DoubleRatchet } from "client-core";

// Create a new double ratchet for Alice.
// Bob identity and shared secret must be obtained prior to double ratchet
// initialization.
let aliceRatchet = DoubleRatchet.initAlice(aliceSk, bobIdentity.public);

// Create a new double ratchet for Alice.
let bobRatchet = DoubleRatchet.initBob(bobSk, bobIdentity);

// Prepare a message and additional authenticated data.
let msg = new TextEncoder("utf-8").encode("Hello, Bobby!");
let msgAad = new TextEncoder("utf-8").encode("A2B");

// Encrypt a message
let encryptedMessage = aliceRatchet.encrypt(msg, msgAad);

// Header and ciphertext should be sent to Bob.
let header = encryptedMessage.header;
let ciphertext = encryptedMessage.ciphertext;

console.log("Ciphertext:", new TextDecoder().decode(ciphertext));

// Bob gets a message from Alice and decrypts it.
let decryptedMsg = bobRatchet.decrypt(header, ciphertext, msgAad);
console.log("Decrypted:", new TextDecoder().decode(decryptedMsg));
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "libclient_core.h"

int main(void) {
  KeyPair* alice_identity = keypair_generate();
  KeyPair* alice_prekey = keypair_generate();
  uint8_t* alice_prekey_public =
      public_key_to_bytes(keypair_to_public(alice_prekey));
  KeyPair* alice_onetime[] = {keypair_generate()};
  uint8_t* alice_signature =
      keypair_sign(alice_identity, alice_prekey_public, PUBLIC_KEY_LEN);

  X3dhInMemProtocol* alice_protocol = x3dh_inmem_protocol_new(
      alice_identity, alice_prekey, alice_signature, *alice_onetime, 1);

  if (!alice_protocol) {
    printf("Error creating alice protocol");
    return -1;
  }

  KeyPair* bob_identity = keypair_generate();
  KeyPair* bob_prekey = keypair_generate();
  PublicKey* bob_prekey_public = keypair_to_public(bob_prekey);
  KeyPair* bob_onetime[] = {keypair_generate()};
  uint8_t* bob_signature = keypair_sign(
      bob_identity, public_key_to_bytes(bob_prekey_public), PUBLIC_KEY_LEN);

  const X3dhInMemProtocol* bob_protocol = x3dh_inmem_protocol_new(
      bob_identity, bob_prekey, bob_signature, *bob_onetime, 1);

  if (!bob_protocol) {
    printf("Error creating alice protocol");
    return -1;
  }

  const X3dhInitMsgBundle* alice_bundle =
      x3dh_inmem_protocol_prepare_init_msg_bundle(
          alice_protocol, keypair_to_public(bob_identity), bob_prekey_public,
          bob_signature, keypair_to_public(bob_onetime[0]));

  if (!alice_bundle) {
    printf("Error creating alice bundle");
    return -1;
  }

  const X3dhInitMsg alice_init_msg = alice_bundle->init_msg;
  const uint8_t* alice_shared_secret = alice_bundle->shared_secret;

  const uint8_t* bob_shared_secret = x3dh_inmem_protocol_derive_shared_secret(
      bob_protocol, alice_init_msg.sender_identity,
      alice_init_msg.sender_ephemeral_key, alice_init_msg.receiver_onetime_key,
      alice_init_msg.nonce, alice_init_msg.ciphertext,
      alice_init_msg.ciphertext_len);

  if (!bob_shared_secret) {
    printf("Error deriving shared secret");
    return 0;
  }

  printf("%s\n", bytes_to_hex(alice_shared_secret, SHARED_KEY_LEN));
  printf("%s\n", bytes_to_hex(bob_shared_secret, SHARED_KEY_LEN));

  DoubleRatchet* alice_ratchet = double_ratchet_init_alice(
      alice_shared_secret, keypair_to_public(bob_identity));

  DoubleRatchet* bob_ratchet =
      double_ratchet_init_bob(bob_shared_secret, bob_identity);

  const u_int8_t* alice_msg = "Hello, Bob!\0";

  EncryptedMessage* msg = double_ratchet_encrypt(alice_ratchet, alice_msg,
                                                 strlen(alice_msg), "A2B", 3);

  DecryptedMessage* decrypted = double_ratchet_decrypt(
      bob_ratchet, msg->header, msg->ciphertext, msg->ciphertext_len, "A2B", 3);

  printf("%.11s\n", decrypted->data);

  return 0;
}
0.1.0

6 months ago