extern crate libsignal_protocol as sig;
use std::time::SystemTime;
use failure::{Error, ResultExt};
use sig::{
stores::{
InMemoryIdentityKeyStore, InMemoryPreKeyStore, InMemorySessionStore,
InMemorySignedPreKeyStore,
},
Address, Context, PreKeyBundle, Serializable, SessionBuilder,
SessionCipher,
};
#[path = "../tests/helpers/mod.rs"]
mod helpers;
cfg_if::cfg_if! {
if #[cfg(feature = "crypto-native")] {
type Crypto = sig::crypto::DefaultCrypto;
} else if #[cfg(feature = "crypto-openssl")] {
type Crypto = sig::crypto::OpenSSLCrypto;
} else {
compile_error!("These tests require one of the crypto features to be enabled");
}
}
fn main() -> Result<(), Error> {
env_logger::init();
let ctx = Context::new(Crypto::default()).unwrap();
let bob_address = Address::new("+14159998888", 1);
let bob_identity_keys = sig::generate_identity_key_pair(&ctx)
.context("Unable to generate bob's keys")?;
let bob_public_identity_key = bob_identity_keys.public();
let bob_pre_keys: Vec<_> = sig::generate_pre_keys(&ctx, 0, 10)
.context("Unable to generate bob's pre-keys")?
.collect();
let pre_key = &bob_pre_keys[0];
let bob_signed_pre_key = sig::generate_signed_pre_key(
&ctx,
&bob_identity_keys,
12,
SystemTime::now(),
)
.context("Unable to generate a signed pre-key for bob")?;
let alice_registration_id = sig::generate_registration_id(&ctx, 0)?;
let alice_identity = sig::generate_identity_key_pair(&ctx)?;
let alice_store_ctx = sig::store_context(
&ctx,
InMemoryPreKeyStore::default(),
InMemorySignedPreKeyStore::default(),
InMemorySessionStore::default(),
InMemoryIdentityKeyStore::new(alice_registration_id, &alice_identity),
)?;
let alice_session_builder =
SessionBuilder::new(&ctx, &alice_store_ctx, &bob_address);
let pre_key_bundle = PreKeyBundle::builder()
.registration_id(42)
.device_id(bob_address.device_id())
.identity_key(&bob_public_identity_key)
.pre_key(pre_key.id(), &pre_key.key_pair().public())
.signed_pre_key(
bob_signed_pre_key.id(),
&bob_signed_pre_key.key_pair().public(),
)
.signature(bob_signed_pre_key.signature())
.build()
.context("Unable to generate the pre-key bundle")?;
alice_session_builder
.process_pre_key_bundle(&pre_key_bundle)
.context("Unable to create a session with bob")?;
let cipher = SessionCipher::new(&ctx, &alice_store_ctx, &bob_address)?;
let message = "Hello, World!";
let encrypted_message = cipher
.encrypt(message.as_bytes())
.context("Encryption failed")?;
let serialized = encrypted_message
.serialize()
.context("Unable to serialize the message for transmission")?;
println!("Encrypted Message: {:?}", serialized.as_slice());
Ok(())
}