# bls-signatures-rs
[![](https://img.shields.io/crates/v/bls-signatures-rs.svg)](https://crates.io/crates/bls-signatures-rs) [![](https://docs.rs/bls-signatures-rs/badge.svg)](https://docs.rs/bls-signatures-rs) [![](https://travis-ci.com/witnet/bls-signatures-rs.svg?branch=master)](https://travis-ci.com/witnet/bls-signatures-rs)

`bls-signatures-rs` is an open source implementation of [Bonneh-Lynn-Shacham (BLS) signatures](https://en.wikipedia.org/wiki/Boneh%E2%80%93Lynn%E2%80%93Shacham) written in Rust. At the moment this implementation only supports the BN256 pairing friendly.

_DISCLAIMER_: This is experimental software. Be careful!

## BN256

This module uses the [BN library](https://github.com/paritytech/bn) to perform elliptic curve operations over the appropriate fields. It provides the following functionalities on top of the bn256 library:

* `derive_public_key`: Derive a public key over the bn256 curve given a secret key.
* `sign`: Sign a message given a secret key.
* `verify`: Given a public key, a signature and a message it verifies whether the signature is valid.
* `aggregate_public_keys`: Aggregate a set of public keys into a single aggregated one.
* `aggregate_signatures`: Aggregate a set of signatures into a single aggregated one.

## Hashing to G1

The algorithm utilized to hash a given message into a point in G1 is try and increment. We discourage its usage in the cases of hashing secret messages since its running time leaks information about the input.
 In any other cases, where the message to be hashed is public, try and increment should be safe. The hashing algorithm utilized is `sha256`.

## Example

Sign, aggregate and verify by using the BN256 curve:

```rust
use bls_signatures_rs::MultiSignature;
use bls_signatures_rs::bn256::Bn256;

fn main() {
    // Inputs: Secret Key, Public Key (derived) & Message

    // Secret key one
    let secret_key_1 =
        hex::decode("c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721").unwrap();

    // Secret key two
    let secret_key_2 =
        hex::decode("a55e93edb1350916bf5beea1b13d8f198ef410033445bcb645b65be5432722f1").unwrap();

    // Derive public keys from secret key
    let public_key_1 = Bn256.derive_public_key(&secret_key_1).unwrap();
    let public_key_2 = Bn256.derive_public_key(&secret_key_2).unwrap();

    let message: &[u8] = b"sample";

    // Sign identical message with two different secret keys
    let sig_1 = Bn256.sign(&secret_key_1, &message).unwrap();
    let sig_2 = Bn256.sign(&secret_key_2, &message).unwrap();

    // Aggregate public keys
    let agg_pub_key = Bn256.aggregate_public_keys(&[&public_key_1, &public_key_2]).unwrap();

    // Aggregate signatures
    let agg_sig = Bn256.aggregate_signatures(&[&sig_1, &sig_2]).unwrap();

    // Check whether the aggregated signature corresponds to the aggregated public key
    let beta = Bn256.verify(&agg_sig, &message, &agg_pub_key).unwrap();
    println!("Successful verification");
}
```

## Adding unsupported curves

This library defines a MultiSignature trait which can be extended in order to use different curves and algorithms.

```rust
pub trait MultiSignature<PublicKey, SecretKey, Signature> {
    type Error;

    fn derive_public_key(&mut self, secret_key: SecretKey) -> Result<Vec<u8>, Self::Error>;

    fn sign(&mut self, secret_key: SecretKey, message: &[u8]) -> Result<Vec<u8>, Self::Error>;

    fn verify(
           &mut self,
           signature: Signature,
           message: &[u8],
           public_key: PublicKey,
     ) -> Result<(), Self::Error>;

    fn aggregate_public_keys(&mut self, public_key: &[PublicKey]) -> Result<Vec<u8>, Self::Error>;

    fn aggregate_signatures(&mut self, public_key: &[Signature]) -> Result<Vec<u8>, Self::Error>;
}
```

## License

`bls-signatures-rs` is published under the [MIT license](https://github.com/witnet/bls-signatures-rs/blob/master/LICENSE)