#encryption #signature #signing #message-authentication

signcryption

该库实现了在Ristretto255或Ed25519上实例化的Toorani-Beheshti签名加密方案

4个版本

0.1.3 2023年8月15日
0.1.2 2023年6月25日
0.1.1 2023年1月9日
0.1.0 2023年1月9日

#914 in 密码学

MIT/Apache

35KB
519

Build Status Crates

Signcryption

Signcryption是一种结合了数字签名和加密功能的密码学技术。它允许发送者验证消息的来源并保护其机密性,同时允许接收者验证消息的真实性并解密它,而无需任何单独的通信渠道。

该库实现了在Ristretto255或Ed25519上实例化的Toorani-Beheshti签名加密方案。

安装

该库目前依赖于libsodium-sys-stable包。您需要先安装libsodium。

https://libsodium.gitbook.io/doc/installation

或者简单地在首次使用时使用该包的fetch-libsodium特性,这将下载并安装当前稳定版本。

将以下内容添加到您的项目中

cargo add signcryption

或者Cargo.toml

[dependencies]
signcryption = "0.1"

使用

更高级的signcryptunsigncrypt函数会自动使用AES-GCM包进行加密。

// 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[..]);

要使用不同的AEAD或进行更底层的控制,您需要直接运行离散步骤函数。要删除aes-gcm包依赖,请在Cargo.toml中设置default-features = false

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)?;

公开验证

验证消息而不学习解密密钥。

verify_public(
  &sig, &sender_id, &recipient_id, &info, 
  &alice_public_key, &ciphertext, Curve::Ed25519
)?;

为什么?

无论以何种顺序组合加密和签名,都存在缺陷

  • 先加密后签名:攻击者可以替换您的签名,使其看起来像他们加密了文件。

  • 先签名后加密:接收者可以重新加密文件并冒充您将文件发送给其他人。

Signcryption在加密阶段之前和之后都执行签名,从而消除了这些缺陷。

替代方案

该包基于由Frank Denis编写的C语言Libsodium-Signcryption库。

许可

所有crates都根据您的选择在以下两种许可下提供

任选其一。

贡献

除非您明确声明,否则您有意提交给作品的所有贡献,根据Apache-2.0许可定义,应如上所述双重许可,不得添加任何额外的条款或条件。

依赖关系

~2.6–5MB
~54K SLoC