0.1.0 • Published 6 months ago
tingl-client-core v0.1.0
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