4 releases
0.1.3 | Aug 15, 2023 |
---|---|
0.1.2 | Jun 25, 2023 |
0.1.1 | Jan 9, 2023 |
0.1.0 | Jan 9, 2023 |
#1245 in Cryptography
35KB
519 lines
Signcryption
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.
Installation
This library currently depends on the libsodium-sys-stable crate. You will need libsodium installed first.
https://libsodium.gitbook.io/doc/installation
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
:
[dependencies]
signcryption = "0.1"
Usage
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
Signcrypt
// 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
sign_before(
&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
Unsigncrypt
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
verify_before(
&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.
verify_public(
&sig, &sender_id, &recipient_id, &info,
&alice_public_key, &ciphertext, Curve::Ed25519
)?;
Why?
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.
Alternatives
This crate is based on the Libsodium-Signcryption library, written in C by Frank Denis.
Licensing
All crates licensed under either of
at your option.
Contribution
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.
Dependencies
~2.6–5.5MB
~62K SLoC