Skip to main content

BLS signatures in c++ (with python bindings)

This project has been archived.

The maintainers of this project have marked this project as archived. No new releases are expected.

Project description

Build PyPI PyPI - Format GitHub

Total alerts Language grade: JavaScript Language grade: Python Language grade: C/C++

BLS Signatures implementation

NOTE: THIS LIBRARY IS A DRAFT AND NOT YET REVIEWED FOR SECURITY

Implements BLS signatures with aggregation as in Boneh, Drijvers, Neven 2018 , using relic toolkit for cryptographic primitives (pairings, EC, hashing). The BLS12-381 curve is used. The original spec is here. This library now implements IETF BLS RFC.

Features:

  • Non-interactive signature aggregation on identical or distinct messages
  • Aggregate aggregates (trees)
  • Efficient verification (only one pairing per distinct message)
  • Security against rogue public key attack, using aggregation info, or proof of possession
  • Aggregate public keys and private keys
  • M/N threshold keys and signatures using Joint-Feldman scheme
  • HD (BIP32) key derivation
  • Key and signature serialization
  • Batch verification
  • Signature division (divide an aggregate by a previously verified signature)
  • JavaScript bindings
  • Python bindings
  • Pure python bls12-381 and signatures

Import the library

#include "bls.hpp"

Creating keys and signatures

// Example seed, used to generate private key. Always use
// a secure RNG with sufficient entropy to generate a seed.
uint8_t seed[] = {0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192,
                  19, 18, 12, 89, 6, 220, 18, 102, 58, 209,
                  82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22};

bls::PrivateKey sk = bls::PrivateKey::FromSeed(seed, sizeof(seed));
bls::PublicKey pk = sk.GetPublicKey();

uint8_t msg[] = {100, 2, 254, 88, 90, 45, 23};

bls::Signature sig = sk.Sign(msg, sizeof(msg));

Serializing keys and signatures to bytes

uint8_t skBytes[bls::PrivateKey::PRIVATE_KEY_SIZE];  // 32 byte array
uint8_t pkBytes[bls::PublicKey::PUBLIC_KEY_SIZE];    // 48 byte array
uint8_t sigBytes[bls::Signature::SIGNATURE_SIZE];    // 96 byte array

sk.Serialize(skBytes);   // 32 bytes
pk.Serialize(pkBytes);   // 48 bytes
sig.Serialize(sigBytes); // 96 bytes

Loading keys and signatures from bytes

// Takes array of 32 bytes
sk = bls::PrivateKey::FromBytes(skBytes);

// Takes array of 48 bytes
pk = bls::PublicKey::FromBytes(pkBytes);

// Takes array of 96 bytes
sig = bls::Signature::FromBytes(sigBytes);

Verifying signatures

// Add information required for verification, to sig object
sig.SetAggregationInfo(bls::AggregationInfo::FromMsg(pk, msg, sizeof(msg)));

bool ok = sig.Verify();

Aggregate signatures for a single message

// Generate some more private keys
seed[0] = 1;
bls::PrivateKey sk1 = bls::PrivateKey::FromSeed(seed, sizeof(seed));
seed[0] = 2;
bls::PrivateKey sk2 = bls::PrivateKey::FromSeed(seed, sizeof(seed));

// Generate first sig
bls::PublicKey pk1 = sk1.GetPublicKey();
bls::Signature sig1 = sk1.Sign(msg, sizeof(msg));

// Generate second sig
bls::PublicKey pk2 = sk2.GetPublicKey();
bls::Signature sig2 = sk2.Sign(msg, sizeof(msg));

// Aggregate signatures together
vector<bls::Signature> sigs = {sig1, sig2};
bls::Signature aggSig = bls::Signature::Aggregate(sigs);

// For same message, public keys can be aggregated into one.
// The signature can be verified the same as a single signature,
// using this public key.
vector<bls::PublicKey> pubKeys = {pk1, pk2};
bls::PublicKey aggPubKey = bls::Signature::Aggregate(pubKeys);

Aggregate signatures for different messages

// Generate one more key and message
seed[0] = 3;
bls::PrivateKey sk3 = bls::PrivateKey::FromSeed(seed, sizeof(seed));
bls::PublicKey pk3 = sk3.GetPublicKey();
uint8_t msg2[] = {100, 2, 254, 88, 90, 45, 23};

// Generate the signatures, assuming we have 3 private keys
sig1 = sk1.Sign(msg, sizeof(msg));
sig2 = sk2.Sign(msg, sizeof(msg));
bls::Signature sig3 = sk3.Sign(msg2, sizeof(msg2));

// They can be noninteractively combined by anyone
// Aggregation below can also be done by the verifier, to
// make batch verification more efficient
vector<bls::Signature> sigsL = {sig1, sig2};
bls::Signature aggSigL = bls::Signature::Aggregate(sigsL);

// Arbitrary trees of aggregates
vector<bls::Signature> sigsFinal = {aggSigL, sig3};
bls::Signature aggSigFinal = bls::Signature::Aggregate(sigsFinal);

// Serialize the final signature
aggSigFinal.Serialize(sigBytes);

Verify aggregate signature for different messages

// Deserialize aggregate signature
aggSigFinal = bls::Signature::FromBytes(sigBytes);

// Create aggregation information (or deserialize it)
bls::AggregationInfo a1 = bls::AggregationInfo::FromMsg(pk1, msg, sizeof(msg));
bls::AggregationInfo a2 = bls::AggregationInfo::FromMsg(pk2, msg, sizeof(msg));
bls::AggregationInfo a3 = bls::AggregationInfo::FromMsg(pk3, msg2, sizeof(msg2));
vector<bls::AggregationInfo> infos = {a1, a2};
bls::AggregationInfo a1a2 = bls::AggregationInfo::MergeInfos(infos);
vector<bls::AggregationInfo> infos2 = {a1a2, a3};
bls::AggregationInfo aFinal = bls::AggregationInfo::MergeInfos(infos2);

// Verify final signature using the aggregation info
aggSigFinal.SetAggregationInfo(aFinal);
ok = aggSigFinal.Verify();

// If you previously verified a signature, you can also divide
// the aggregate signature by the signature you already verified.
ok = aggSigL.Verify();
vector<bls::Signature> cache = {aggSigL};
aggSigFinal = aggSigFinal.DivideBy(cache);

// Final verification is now more efficient
ok = aggSigFinal.Verify();

Aggregate private keys

vector<bls::PrivateKey> privateKeysList = {sk1, sk2};
vector<bls::PublicKey> pubKeysList = {pk1, pk2};

// Create an aggregate private key, that can generate
// aggregate signatures
const bls::PrivateKey aggSk = bls::PrivateKey::Aggregate(
        privateKeys, pubKeys);

bls::Signature aggSig3 = aggSk.Sign(msg, sizeof(msg));

HD keys

// Random seed, used to generate master extended private key
uint8_t seed[] = {1, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192,
                  19, 18, 12, 89, 6, 220, 18, 102, 58, 209,
                  82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22};

bls::ExtendedPrivateKey esk = bls::ExtendedPrivateKey::FromSeed(
        seed, sizeof(seed));

bls::ExtendedPublicKey epk = esk.GetExtendedPublicKey();

// Use i >= 2^31 for hardened keys
bls::ExtendedPrivateKey skChild = esk.PrivateChild(0)
                                .PrivateChild(5);

bls::ExtendedPublicKey pkChild = epk.PublicChild(0)
                               .PublicChild(5);

// Serialize extended keys
uint8_t buffer1[bls::ExtendedPublicKey::EXTENDED_PUBLIC_KEY_SIZE];   // 93 bytes
uint8_t buffer2[bls::ExtendedPrivateKey::EXTENDED_PRIVATE_KEY_SIZE]; // 77 bytes

pkChild.Serialize(buffer1);
skChild.Serialize(buffer2);

Prepend PK method

// Can use proofs of possession to avoid keeping track of metadata
PrependSignature prepend1 = sk1.SignPrepend(msg, sizeof(msg));
PrependSignature prepend2 = sk2.SignPrepend(msg, sizeof(msg));

std::vector<PublicKey> prependPubKeys = {pk1, pk2};
uint8_t messageHash[BLS::MESSAGE_HASH_LEN];
Util::Hash256(messageHash, msg, sizeof(msg));
std::vector<const uint8_t*> hashes = {messageHash, messageHash};

std::vector<PrependSignature> prependSigs = {prepend1, prepend2};
PrependSignature prependAgg = PrependSignature::Aggregate(prependSigs);

prependAgg.Verify(hashes, prependPubKeys);

Build

Cmake 3.14+, a c++ compiler, and python3 (for bindings) are required for building.

git submodule update --init --recursive

mkdir build
cd build
cmake ../
cmake --build . -- -j 6

Run tests

./build/src/runtest

Run benchmarks

./build/src/runbench

Link the library to use it

g++ -Wl,-no_pie  -Ibls-signatures/contrib/relic/include -Ibls-signatures/build/contrib/relic/incl
ude -Ibls-signatures/src/  -L./bls-signatures/build/ -l bls  yourfile.cpp

Notes on dependencies

Changes performed to relic: Added config files for Chia, and added gmp include in relic.h, new ep_map and ep2_map, new ep_pck and ep2_pck. Custom inversion function. Note: relic is used with the Apache 2.0 license.

Libsodium and GMP are optional dependencies: libsodium gives secure memory allocation, and GMP speeds up the library by ~ 3x. To install them, either download them from github and follow the instructions for each repo, or use a package manager like APT or brew.

Discussion

Discussion about this library and other Chia related development is on Keybase. Install Keybase, and run the following to join the Chia public channels:

keybase team request-access chia_network.public

Code style

  • Always use uint8_t for bytes
  • Use size_t for size variables
  • Uppercase method names
  • Prefer static constructors
  • Avoid using templates
  • Objects allocate and free their own memory
  • Use cpplint with default rules

There are three types of signatures: InsecureSignatures (simple signatures which are not secure by themselves, due to rogue public keys), Signatures (secure signatures that require AggregationInfo to aggregate), and PrependSignatures, which prepend public keys to messages, making them secure.

ci Building

The primary build process for this repository is to use GitHub Actions to build binary wheels for MacOS, Linux (x64 and aarch64), and Windows and publish them with a source wheel on PyPi. See .github/workflows/build.yml. CMake uses FetchContent to download pybind11 for the Python bindings. Building is then managed by cibuildwheel. Further installation is then available via pip install blspy e.g. The ci builds include GMP and libsoduium.

Contributing and workflow

Contributions are welcome and more details are available in chia-blockchain's CONTRIBUTING.md.

The master branch is usually the currently released latest version on PyPI. Note that at times bls-signatures/blspy will be ahead of the release version that chia-blockchain requires in it's master/release version in preparation for a new chia-blockchain release. Please branch or fork master and then create a pull request to the master branch. Linear merging is enforced on master and merging requires a completed review. PRs will kick off a GitHub actions ci build and analysis of bls-signatures at lgtm.com. Please make sure your build is passing and that it does not increase alerts at lgtm.

Specification and test vectors

The specification and test vectors can be found here. Test vectors can also be seen in the python or cpp test files.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

blspy-0.2b11.tar.gz (240.2 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

blspy-0.2b11-cp38-cp38-win_amd64.whl (2.0 MB view details)

Uploaded CPython 3.8Windows x86-64

blspy-0.2b11-cp38-cp38-manylinux2014_aarch64.whl (367.3 kB view details)

Uploaded CPython 3.8

blspy-0.2b11-cp38-cp38-manylinux2010_x86_64.whl (381.4 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.12+ x86-64

blspy-0.2b11-cp38-cp38-macosx_10_14_x86_64.whl (533.8 kB view details)

Uploaded CPython 3.8macOS 10.14+ x86-64

blspy-0.2b11-cp37-cp37m-win_amd64.whl (2.0 MB view details)

Uploaded CPython 3.7mWindows x86-64

blspy-0.2b11-cp37-cp37m-manylinux2010_x86_64.whl (382.2 kB view details)

Uploaded CPython 3.7mmanylinux: glibc 2.12+ x86-64

blspy-0.2b11-cp37-cp37m-macosx_10_14_x86_64.whl (528.7 kB view details)

Uploaded CPython 3.7mmacOS 10.14+ x86-64

File details

Details for the file blspy-0.2b11.tar.gz.

File metadata

  • Download URL: blspy-0.2b11.tar.gz
  • Upload date:
  • Size: 240.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2b11.tar.gz
Algorithm Hash digest
SHA256 b7ffeb05eb8eed814f985d3e256c3f865989c762dd15af5d41993501478212fc
MD5 9ed1a4ba65fa298e06ba99faeb6c49eb
BLAKE2b-256 2d986692989a10731c5909205bf517c26b7fb27c299922f9191e3a2bf046b82f

See more details on using hashes here.

File details

Details for the file blspy-0.2b11-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: blspy-0.2b11-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 2.0 MB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2b11-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 5a09b84bb6d6534c866aaa23d704f2dd65773c57a099dbb87c8ef534e74460e8
MD5 8beeb1b6857367a992cb0394c18a0a0e
BLAKE2b-256 b0586b265389e9a2e2cf1f52ccc25aa56a3ed5f6f12687ab27358bdf71d44555

See more details on using hashes here.

File details

Details for the file blspy-0.2b11-cp38-cp38-manylinux2014_aarch64.whl.

File metadata

  • Download URL: blspy-0.2b11-cp38-cp38-manylinux2014_aarch64.whl
  • Upload date:
  • Size: 367.3 kB
  • Tags: CPython 3.8
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/44.0.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.8.2

File hashes

Hashes for blspy-0.2b11-cp38-cp38-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 bf23e6a3a9d4814c9db836f434c868ee6dc71be9ca67d2d5e52d455aab283878
MD5 289fd91d0727ecc0a82ce9c66d9780c6
BLAKE2b-256 c3d8ceb4f4c80e37f099985116eac136c995090947d4515e48b77ca1a0eac2ce

See more details on using hashes here.

File details

Details for the file blspy-0.2b11-cp38-cp38-manylinux2010_x86_64.whl.

File metadata

  • Download URL: blspy-0.2b11-cp38-cp38-manylinux2010_x86_64.whl
  • Upload date:
  • Size: 381.4 kB
  • Tags: CPython 3.8, manylinux: glibc 2.12+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.7.7

File hashes

Hashes for blspy-0.2b11-cp38-cp38-manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 4bc30ef09185eee4339715824f40dcb7883f8d916d90eb00b8e3f1d45ae96a84
MD5 783db921009d84dab2925a65b79f0caa
BLAKE2b-256 3900540f37c22918132c770d6b32a97aa1eaa1803802507ce02aba7a3d7f4f99

See more details on using hashes here.

File details

Details for the file blspy-0.2b11-cp38-cp38-macosx_10_14_x86_64.whl.

File metadata

  • Download URL: blspy-0.2b11-cp38-cp38-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 533.8 kB
  • Tags: CPython 3.8, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2b11-cp38-cp38-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 8255cf313ff6c8d2e03464b6eecc6d3fac65277cdba5a9ae7d889a531e1454cd
MD5 799f70300efcd5dfe6abd9077437dc1a
BLAKE2b-256 3fb9eb54a6bd487138fd69b698dc3396f8bf833286360957cd30f9d7407daffc

See more details on using hashes here.

File details

Details for the file blspy-0.2b11-cp37-cp37m-win_amd64.whl.

File metadata

  • Download URL: blspy-0.2b11-cp37-cp37m-win_amd64.whl
  • Upload date:
  • Size: 2.0 MB
  • Tags: CPython 3.7m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2b11-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 d0793c955ea2d7ea23abdbd17eb51494e61b5a4a2aa8377d49efb760f8fba976
MD5 92523e4391c77ef2d6d8d477d5c839ce
BLAKE2b-256 71f69f3fcbfb456246538a4d9948e13de5ce2dd156117512642b1ad10c4817ff

See more details on using hashes here.

File details

Details for the file blspy-0.2b11-cp37-cp37m-manylinux2010_x86_64.whl.

File metadata

  • Download URL: blspy-0.2b11-cp37-cp37m-manylinux2010_x86_64.whl
  • Upload date:
  • Size: 382.2 kB
  • Tags: CPython 3.7m, manylinux: glibc 2.12+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.7.7

File hashes

Hashes for blspy-0.2b11-cp37-cp37m-manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 4adccbf12d465103cbbca8892856260aa94a3115a3a2b1a9edd07ad8c1f2201d
MD5 d544d9a1326672131e83a42cb2f65224
BLAKE2b-256 f811e7d7229c754e35b6abf95db0886b81581f4eae625a32f01aeeaa087d25bf

See more details on using hashes here.

File details

Details for the file blspy-0.2b11-cp37-cp37m-macosx_10_14_x86_64.whl.

File metadata

  • Download URL: blspy-0.2b11-cp37-cp37m-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 528.7 kB
  • Tags: CPython 3.7m, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2b11-cp37-cp37m-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 1b5863a238beea705ebe75a2789772047100bfe21f8ab77bbda192fa024a9b9b
MD5 df954c33e768a47501c86072a9a45222
BLAKE2b-256 183de4460a0c117ce2e6a4e2403373a7b95610b03c3b9b1f9febc30e3de6953a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page