Skip to main content

BLS signatures in c++ (with python bindings)

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. You can follow the recipe used to build python wheels for multiple platforms in .github/workflows/

Discussion

Discussion about this library and other Chia related development is in Chia's public Keybase channels.

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 and relic from a chia relic forked reporitory. Building is then managed by cibuildwheel. Further installation is then available via pip install blspy e.g. The ci builds include GMP and soduium.

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.2rc1.tar.gz (242.9 kB view details)

Uploaded Source

Built Distributions

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

Uploaded CPython 3.8 Windows x86-64

blspy-0.2rc1-cp38-cp38-manylinux2014_aarch64.whl (620.6 kB view details)

Uploaded CPython 3.8

blspy-0.2rc1-cp38-cp38-manylinux2010_x86_64.whl (701.0 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.12+ x86-64

blspy-0.2rc1-cp38-cp38-macosx_10_14_x86_64.whl (537.7 kB view details)

Uploaded CPython 3.8 macOS 10.14+ x86-64

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

Uploaded CPython 3.7m Windows x86-64

blspy-0.2rc1-cp37-cp37m-manylinux2010_x86_64.whl (701.7 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.12+ x86-64

blspy-0.2rc1-cp37-cp37m-macosx_10_14_x86_64.whl (532.5 kB view details)

Uploaded CPython 3.7m macOS 10.14+ x86-64

File details

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

File metadata

  • Download URL: blspy-0.2rc1.tar.gz
  • Upload date:
  • Size: 242.9 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.2rc1.tar.gz
Algorithm Hash digest
SHA256 adfd530254a32e6b206a1bf7c0cc75c08708c5fa609cbe5868ae70657bb70ad6
MD5 18ba84ff1052c65dcf015ce5a3fcda26
BLAKE2b-256 e42b5867a5dc59b99a1b8baceb4b9a9ac36c61b26d1e8cd6292a19e70cd92a7d

See more details on using hashes here.

Provenance

File details

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

File metadata

  • Download URL: blspy-0.2rc1-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.2rc1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 0fcab53ae8806f8452c2c56f84ea756fded14c5c5a55b540517a8f1e091d8b85
MD5 5db6553f375990d76ab4aa5a9e8cf6b4
BLAKE2b-256 986871dbbfb17f096e6afbf5d7ce5673b0f6403632cf1bc2dc13e70c3913e1a5

See more details on using hashes here.

Provenance

File details

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

File metadata

  • Download URL: blspy-0.2rc1-cp38-cp38-manylinux2014_aarch64.whl
  • Upload date:
  • Size: 620.6 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.2rc1-cp38-cp38-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 8816cf958032c37bcabab6b7bafb4190020a2ba4b64d7b215f03f9836aad2722
MD5 e4a5d7e7f14b7f59fbbddc937c21ac32
BLAKE2b-256 8ff1c9c7dda73e46ad9b392b93badd96ed5db36f7482cc0ea553fd7fba21c55a

See more details on using hashes here.

Provenance

File details

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

File metadata

  • Download URL: blspy-0.2rc1-cp38-cp38-manylinux2010_x86_64.whl
  • Upload date:
  • Size: 701.0 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.2rc1-cp38-cp38-manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 d3898e0ec96479fe5adbe4694b1d3bcbe938c4594ede4d46d7e391495ed5c9f2
MD5 ce483721dba923dc1dd46119dca41b52
BLAKE2b-256 95bf397f3d4894958f109d3228bbd0e8d253f22bf9870ea403773f6656a92da8

See more details on using hashes here.

Provenance

File details

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

File metadata

  • Download URL: blspy-0.2rc1-cp38-cp38-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 537.7 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.2rc1-cp38-cp38-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 a305ec8c3958383043697f6dd191764e6211ee51fb219dd6e3dc1abd1d4ea425
MD5 a4abfecd493eed296ed7956fa9ddb745
BLAKE2b-256 45add56ffcee14a56af59ee60a67463a7093392b6605784d3e04b729293c42cf

See more details on using hashes here.

Provenance

File details

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

File metadata

  • Download URL: blspy-0.2rc1-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.2rc1-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 8dae578dc5f8af137c48373334c02650ee2159b75415cd44a9571442dbcfbd93
MD5 ebb70dcc4cbf1a18ae76161726371699
BLAKE2b-256 74db920f356018a0ad68709ebe802b9bd77deb9fc82d4324dc0eb7f9df4aba55

See more details on using hashes here.

Provenance

File details

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

File metadata

  • Download URL: blspy-0.2rc1-cp37-cp37m-manylinux2010_x86_64.whl
  • Upload date:
  • Size: 701.7 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.2rc1-cp37-cp37m-manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 a6769a8d381f7c9331faef1013de8bc3b99230667efde081c83d1610e2167f6c
MD5 8653d3b97d9d338b6df3beae10b23b34
BLAKE2b-256 efb66965b12de9c3d7fa8cc06dd46f132bfe156322007a257c3ea16ee62d6fbd

See more details on using hashes here.

Provenance

File details

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

File metadata

  • Download URL: blspy-0.2rc1-cp37-cp37m-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 532.5 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.2rc1-cp37-cp37m-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 6d6eac7a36985db267bc344ef392cbe34103f2cd9af9116eb819dc87b87cd478
MD5 8157383c09f914a54f50ed812dfa8a9d
BLAKE2b-256 da121296c1df946fd3105747b0c6d6cfc844763073ff40c6fca7a7f8084a8312

See more details on using hashes here.

Provenance

Supported by

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