#bls #bn256 #bn128 #crypto #bn


Open source implementation of Barreto-Naehrig (BN) aggregate signatures written in Rust

1 unstable release

0.0.1 Feb 10, 2023

#2 in #bn128

MIT license

603 lines


bn254 is an open-source Rust implementation of aggregate signatures over the pairing-friendly elliptic curve BN254 (Barreto-Naehrig (BN)).

This curve is also known as bn256 or bn128 (alt-bn128) referred to the bits of security. The bits of security of bn254 dropped from 128 to around 100 after the new algorithms of Kim-Barbulescu.

DISCLAIMER: This is experimental software. Be careful!


This module uses the substrate-bn library to perform elliptic curve operations over the appropriate fields. It provides the following functionalities:

  • 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.

Signature and public aggregation can be done directly with the + or - operators.

Hashing to G1

The algorithm used for hashing a given message into a point in G1 follows the "try-and-increment" method. We discourage its usage in the cases of hashing secret messages since its running time leaks information about the input.

In other cases, where the message to be hashed is public, "try-and-increment" should be safe. The hashing algorithm utilized is sha256.


Sign, aggregate and verify by using the bn254 curve:

use bn254::{PrivateKey, PublicKey, ECDSA};

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

    // Secret key one
    let private_key_1_bytes = hex::decode("c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721").unwrap();
    let private_key_1 = PrivateKey::try_from(private_key_1_bytes.as_ref()).unwrap();

    // Secret key two
    let private_key_2_bytes = hex::decode("a55e93edb1350916bf5beea1b13d8f198ef410033445bcb645b65be5432722f1").unwrap();
    let private_key_2 = PrivateKey::try_from(private_key_2_bytes.as_ref()).unwrap();

    // Derive public keys from secret key
    let public_key_1 = PublicKey::from_private_key(&private_key_1);
    let public_key_2 = PublicKey::from_private_key(&private_key_2);

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

    // Sign identical message with two different secret keys
    let signature_1 = ECDSA::sign(&message, &private_key_1).unwrap();
    let signature_2 = ECDSA::sign(&message, &private_key_2).unwrap();

    // Aggregate public keys
    let aggregate_pub_key = public_key_1 + public_key_2;

    // Aggregate signatures
    let aggregate_sig = signature_1 + signature_2;

    // Check whether the aggregate signature corresponds to the aggregated
    // public_key
    ECDSA::verify(&message, &aggregate_sig, &aggregate_pub_key).unwrap();
    println!("Successful aggregate signature verification");


bn254 is published under the MIT license


~42K SLoC