libsaxolotl v0.1
libsaxolotl implements the Axoltol protocol using curve25519 from libsodium in a LGPLv3+ library.
this library implements a variation, where the skipped header keys are not retained and hence not used when trying to decrypt out-of-band messages.
The axolotl context is 769 bytes, with 16 slots for the latest missed message keys. The initial handshake message (which can be produced in bulk and used for setting up channels asynchronously) is 96 bytes. Encrypted messages have an overhead of 128 bytes.
API
void axolotl_genid(Axolotl_KeyPair * keys);
Initializes a long-term identity key. This long-term key is the authenticating the persona to all peers.
void axolotl_prekey(Axolotl_PreKey *prekey, Axolotl_ctx *ctx, const Axolotl_KeyPair *keypair);
Creates the initial handshake to be exchanged for setting up an Axolotl channel. The pointer to the prekey is the initial packet that needs to be shared with 1 peer, reuse of these prekeys is not recommended. ctx is a pointer to a new Axolotl_ctx object, which needs to be preserved across the life-time of the connection. keypair is the long-term identity key for the persona generating the handshake message.
It is important to note that each prekey is coupled with a context, for correct setup the context according to the prekey must be used.
Generating and serving many of these prekeys centrally allows for asynchronous messaging. but this is not necessary.
int axolotl_handshake(Axolotl_ctx* ctx, const Axolotl_PreKey *prekey);
Receives an initial handshake and derives the initial context. ctx is the persistent context of the Axolotl channel. prekey is one of the communicating peers prekeys, this should be discarded, and never used again after using once. Both peers must execute this with each others prekeys before they can exchange messages.
The ctx must be the one coupled with the prekeys sent to the peer. The prekeys similarly must be the one associated with the ctx of the peer.
void axolotl_box(Axolotl_ctx *ctx, uint8_t *out, int *out_len, const uint8_t *in, const int in_len);
Encrypts a message in using the axolotl context ctx into out;
int axolotl_box_open(Axolotl_ctx *ctx, uint8_t *out, int *out_len, const uint8_t *in, const int in_len);
decrypts a message in using the axolotl context ctx into out;
a quick example for exchange between alice and bob:
#include "axolotl.h" void main(void) { Axolotl_ctx alice_ctx, bob_ctx; Axolotl_KeyPair alice_id, bob_id; Axolotl_PreKey alice_prekey, bob_prekey; // init long-term identity keys axolotl_genid(&alice_id); axolotl_genid(&bob_id); axolotl_prekey(&alice_prekey, &alice_ctx, &alice_id); axolotl_prekey(&bob_prekey, &bob_ctx, &bob_id); // both derive the ctx from their exchanged prekey msg axolotl_handshake(&alice_ctx, &bob_prekey); axolotl_handshake(&bob_ctx, &alice_prekey); uint8_t out[4096], out2[4096]; int outlen,outlen2; axolotl_box(&alice_ctx, out, &outlen, (const uint8_t *) "howdy", 6); if(axolotl_box_open(&bob_ctx, out2, &outlen2, out, outlen)!=0) { // fail printf("fail :/\n"); exit(1); } printf("%d %s\n", outlen2, out2); }