#signature #ring #public-key #secret-key #crypto #blsag

no-std orodruin

Safe Rust Monero-like bLSAG ring signatures on Ristretto curve

2 unstable releases

0.2.0 Nov 7, 2024
0.1.0 Jun 28, 2024

#1008 in Cryptography

Download history 14/week @ 2024-09-14 6/week @ 2024-09-21 5/week @ 2024-09-28 102/week @ 2024-11-02 19/week @ 2024-11-09 5/week @ 2024-11-16 2/week @ 2024-11-23

128 downloads per month

AGPL-3.0-only

28KB
517 lines

Orodruin

Safe Rust Monero-like bLSAG ring signatures on Ristretto curve, as described in Zero to Monero.

Ring signature

A "ring" is a set of public keys. A ring signature is a signature that can only be forged by a member of the ring, and while you can verify its authenticity, you cannot identify which member forged it.

This crate implements bLSAG, a kind of ring signature where a different signatures issued by the same key can be proved to be linked together (without breaking the anonymity). You may want to use single-use keys to avoid linkability.

Typical applications are anonymous voting systems and anonymous transactions (e.g. Monero).

Explanations and proof of correctness are given in this short article.

Features

  • Sign (feature alloc)
  • Verify (no-std)
  • Generic for cryptographic 512-bit hashers that impl digest::Digest (e.g. sha2) (feature digest)
  • Impl for blake2b-simd (feature blake2b)
  • You can easily impl other hashers
  • No guarantee about constant-time operation.
  • No guarantee about side-channel attack mitigation.
  • MSRV 1.75.0

Secret key, public key, key image types are 32 bytes each. Signature for a ring of N public keys is at least 64+32N bytes.

Example

use orodruin::*;

let mut rng = rand::thread_rng();
let mut hasher = sha2::Sha512::default();

let secret_keys: Vec<SecretKey> = (0..4).map(|_| SecretKey::random(&mut rng)).collect();
let ring: Vec<PublicKey> = secret_keys.iter().map(SecretKey::public_key).collect();

for (i, secret_key) in secret_keys.into_iter().enumerate() {
	let message = i.to_be_bytes();
	let signature = sign(secret_key, &ring, i, &message, &mut rng, &mut hasher);
	assert_eq!(signature.verify(ring.iter(), &message, &mut hasher), Ok(()));
}

You can check whether two valid signatures have been signed by the same secret key by checking whether their .key_image are equal.

Disclaimer

I am a student in cryptology and computer security (as of 2024), but I am not an expert in elliptic curves nor have I made a security proof for this algorithm. This crate has not been reviewed by an expert. Use at your own risk.

This algorithm is vulnerable to the quantum computer: its security is based on the discrete logarithm problem, which can be solved in polynomial time by the Shor's algorithm. Anonymity and non-slanderability are not quantum-safe. Post-quantum ring signatures exist but have bigger keys and signatures (kilobytes).

Name

In Lord of the Rings, Orodruin is the volcano where the Ring of power was forged and destroyed. As the crate Nazgul served as inspiration for the implementation details, we stay in the theme.

License

Support me via LiberaPay

GNU AGPL v3, CopyLeft 2024 Pascal Engélibert (why copyleft?)

All rights granted to Axiom-Team (association loi 1901, France).

Implementation details inspired by nazgul.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Dependencies

~1.5–2.3MB
~50K SLoC