Crates.io | signature_bbs_plus |
lib.rs | signature_bbs_plus |
version | 0.37.0 |
source | src |
created_at | 2021-04-06 22:40:29.550332 |
updated_at | 2022-05-09 17:52:15.962434 |
description | The Ockam BBS+ signature impementation. |
homepage | https://github.com/build-trust/ockam |
repository | https://github.com/build-trust/ockam/blob/develop/implementations/rust/ockam/signature_bbs_plus |
max_upload_size | |
id | 380049 |
size | 86,363 |
Ockam is a library for building devices that communicate securely, privately and trustfully with cloud services and other devices.
In order to support a variety of proving protocols, this crate implements the BBS+ signature scheme which can be used to generate zero-knowledge proofs about signed attributes and the signatures themselves.
The main Ockam has optional dependency on this crate.
Add this to your Cargo.toml
:
[dependencies]
signature_bbs_plus = "0.37.0"
[dependencies]
signature_bbs_plus = { version = "0.37.0" , default-features = false }
Please note that Cargo features are unioned across the entire dependency
graph of a project. If any other crate you depend on has not opted out of
signature_bbs_plus
default features, Cargo will build signature_bbs_plus
with the std
feature enabled whether or not your direct dependency on signature_bbs_plus
has default-features = false
.
The BBS+ scheme allows the Signer and Holder to be two separate parties. This is often the case, particularly in the case of verifiable credentials.
To generate a new key pair for signing, call the Issuer::new_keys
API. A Short Group Signature allows a set of messages
to be signed with a single key. BBS+ can sign any number of messages at the expense of a bigger public key. This implementation
uses curve BLS12-381 and Blake2b-512 as a hash.
let (public_key, secret_key) = Issuer::new_keys(&mut rand::thread_rng())?;
Message Generators are per-message cryptographic information input into the BBS+ algorithm. They are derived from the public key, and the number of messages the key will be used to sign.
To sign messages, call the Issuer::sign
API.
let (public_key, secret_key) = Issuer::new_keys(&mut rand::thread_rng())?;
let num_messages = 4;
let generators = MessageGenerators::from_public_key(public_key, num_messages);
let messages = [
Message::hash(b"message 1"),
Message::hash(b"message 2"),
Message::hash(b"message 3"),
Message::hash(b"message 4"),
];
let signature = Issuer::sign(&secret_key, &generators, &messages)?;
To create blind signatures, we first need to establish a blind signature context. This is done with the Prover::new_blind_signature_context
API. This function takes an optional slice of pre-committed messages. In this example, an empty slice is used, indicating
no pre-committed messages. The generators, a random nonce, and the RNG are also used.
With the context and secret key, the blind signature is created by calling Issuer::blind_sign
.
let nonce = Nonce::random(&mut rng);
let (context, blinding) =
Prover::new_blind_signature_context(&mut [][..], &generators, nonce, &mut rng)?;
let mut messages = [
(0, Message::hash(b"firstname")),
(1, Message::hash(b"lastname")),
(2, Message::hash(b"age")),
(3, Message::hash(b"allowed")),
];
let blind_signature =
Issuer::blind_sign(&context, &secret_key, &generators, &mut messages[..], nonce)?;
Unblinding the signature uses the blinding
information provided by the blinding signature context. The function to_unblinded
takes the blinding
and returns a Signature
.
let signature = blind_signature.to_unblinded(blinding);
Once the signature has been unblinded, it can be used to verify the messages, using the public key. This is done by calling
the Signature::verify
function. Calling Choice::unwrap_u8
on the result of verify
returns 1 when verification succeeds.
let signature = blind_signature.to_unblinded(blinding);
let messages = [
Message::hash(b"message 1"),
Message::hash(b"message 2"),
Message::hash(b"message 3"),
Message::hash(b"message 4"),
];
let res = signature.verify(&public_key, &generators, messages.as_ref());
assert_eq!(res.unwrap_u8(), 1);
use short_group_signatures_core::{error::Error, lib::*};
use signature_bbs_plus::{Issuer, MessageGenerators, Prover};
fn main() -> Result<(), Error> {
let mut rng = rand::thread_rng();
let (public_key, secret_key) = Issuer::new_keys(&mut rng)?;
let num_messages = 4;
let generators = MessageGenerators::from_public_key(public_key, num_messages);
let nonce = Nonce::random(&mut rng);
let (context, blinding) =
Prover::new_blind_signature_context(&mut [][..], &generators, nonce, &mut rng)?;
let mut messages = [
(0, Message::hash(b"firstname")),
(1, Message::hash(b"lastname")),
(2, Message::hash(b"age")),
(3, Message::hash(b"allowed")),
];
let blind_signature =
Issuer::blind_sign(&context, &secret_key, &generators, &mut messages[..], nonce)?;
let signature = blind_signature.to_unblinded(blinding);
// Remove index
let messages = [messages[0].1, messages[1].1, messages[2].1, messages[3].1];
let res = signature.verify(&public_key, &generators, messages.as_ref());
assert_eq!(res.unwrap_u8(), 1);
Ok(())
}
This code is licensed under the terms of the Apache License 2.0.