created_at2023-01-09 00:15:04.041493
updated_at2023-08-15 06:34:20.077112
descriptionLibrary implementing the Toorani-Beheshti signcryption scheme instantiated over Ristretto255 or Ed25519
Mitchell Berry (mberry)



Build Status Crates


Signcryption is a cryptographic technique that combines the functionality of both digital signatures and encryption. It allows a sender to both authenticate the origin of a message and protect its confidentiality, while also allowing the recipient to verify the authenticity of the message and decrypt it without requiring any separate communication channels.

This library implements the Toorani-Beheshti signcryption scheme instantiated over Ristretto255 or Ed25519.


This library currently depends on the libsodium-sys-stable crate. You will need libsodium installed first.

Or simply use the fetch-libsodium feature of this crate on first use which will download and install the current stable version.

To add to your project:

cargo add signcryption

or in Cargo.toml:

signcryption = "0.1"


The higher level signcrypt and unsigncrypt functions automatically handle encryption using the AES-GCM crate.

// Default uses Ristretto255
let alice_keys = Keypair::default();
let bob_keys = Keypair::default();

let alice_public_key = alice_keys.public.clone();
let bob_public_key = bob_keys.public.clone();

let msg = "Hello".as_bytes();

// Sign and encrypt, returns a SignCrypt struct
let ciphertext = signcrypt(&alice_keys, &bob_public_key, &msg)?;

// Verify and decrypt, returns a plaintext Vec<u8>
let plaintext = unsigncrypt(ciphertext, &alice_public_key, &bob_keys)?;

assert_eq!(payload , &plaintext[..]);

To use a different AEAD or for lower level control you'll need to run through the discrete step functions themselves. To remove the aes-gcm crate dependency set default-features = false in Cargo.toml


// Initialise state
let mut state = SignState::default();

// Using Ed25519 keys this time
let alice_keys = Keypair::new(Curve::Ed25519);
let bob_keys = Keypair::new(Curve::Ed25519);

// Shared secret for encryption
let mut crypt_key = [0u8; SHAREDBYTES];

let msg = "Hello".as_bytes()

// Additional Authenticated Data if desired
let sender_id = "alice".as_bytes()
let recipient_id = "bob".as_bytes()
let info = "rust-signcryption".as_bytes()

// Sign plaintext
  &mut state, &mut crypt_key, &sender_id, &recipient_id, &info, 
  &alice.expose_secret(), &bob.public, msg, Curve::Ed25519

// Encrypt here with your desired AEAD using crypt_key eg. //
// let cipher = ChaCha20Poly1305::new(&crypt_key);         //

// Sign ciphertext
let mut sig = [0u8; SIGNBYTES];
sign_after(&mut state, &mut sig, &alice.expose_secret(), &ciphertext, Curve::Ed25519);

// Send ciphertext, signature and any AAD to recipient


let mut state = SignState::default();
let mut crypt_key = [0u8; SHAREDBYTES];

// Additional Authenticated Data used to signcrypt the message
let sender_id = "alice".as_bytes()
let recipient_id = "bob".as_bytes()
let info = "rust-signcryption".as_bytes()

// Verify and get shared secret
  &mut state, &mut crypt_key, &sig, &sender_id,
  &recipient_id, &info, &alice_public_key,
  &bob.expose_secret(), Curve::Ed25519

// Decrypt with crypt_key //

// Verify after
verify_after(&mut state, &sig, &alice_public_key, &ciphertext, Curve::Ed25519)?;

Public Verification

Verify the message without learning the decryption key.

  &sig, &sender_id, &recipient_id, &info, 
  &alice_public_key, &ciphertext, Curve::Ed25519


Combining encryption and signing has flaws either way you order them:

  • Encrypt then Sign: An attacker can replace your signature, making it seem as though they encrypted the file.

  • Sign then Encrypt: The recipient can re-encrypt the file and impersonate you sending the file to someone else.

Signcryption performs signing before and after the encryption stage, negating these flaws.


This crate is based on the Libsodium-Signcryption library, written in C by Frank Denis.


All crates licensed under either of

at your option.


Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Commit count: 34

cargo fmt