Skip to main content

BLS signatures in c++ (with python bindings)

Project description

BLS Signatures implementation

Build PyPI PyPI - Format GitHub

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

NOTE: THIS LIBRARY IS A DRAFT AND NOT YET REVIEWED FOR SECURITY NOTE: THIS LIBRARY WAS SHIFTED TO THE IETF BLS SPECIFICATION ON 7/16/20 SOME DOCUMENTATION IS NOT YET UPDATED

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 the #dev channle of 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 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.

Libsodium license

The libsodium static library is licensed under the ISC license which requires the following copyright notice.

ISC License

Copyright (c) 2013-2020 Frank Denis <j at pureftpd dot org>

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

GMP license

GMP is distributed under the GNU LGPL v3 license

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.2.1.tar.gz (252.1 kB view details)

Uploaded Source

Built Distributions

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

Uploaded CPython 3.8 Windows x86-64

blspy-0.2.1-cp38-cp38-manylinux2014_aarch64.whl (686.7 kB view details)

Uploaded CPython 3.8

blspy-0.2.1-cp38-cp38-manylinux2010_x86_64.whl (787.9 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.12+ x86-64

blspy-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl (640.5 kB view details)

Uploaded CPython 3.8 macOS 10.14+ x86-64

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

Uploaded CPython 3.7m Windows x86-64

blspy-0.2.1-cp37-cp37m-manylinux2014_aarch64.whl (692.4 kB view details)

Uploaded CPython 3.7m

blspy-0.2.1-cp37-cp37m-manylinux2010_x86_64.whl (788.4 kB view details)

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

blspy-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl (634.3 kB view details)

Uploaded CPython 3.7m macOS 10.14+ x86-64

File details

Details for the file blspy-0.2.1.tar.gz.

File metadata

  • Download URL: blspy-0.2.1.tar.gz
  • Upload date:
  • Size: 252.1 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.48.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2.1.tar.gz
Algorithm Hash digest
SHA256 857c290885723d100c2baf2d3d47252cfec27d41d04647e4351546d0f5dbc367
MD5 70f7f39ef7384a261f0ce2caa9017667
BLAKE2b-256 5561ff137d46be02cd76ca7a3b73afa7486f43f52f60f096a4065b782c16730a

See more details on using hashes here.

File details

Details for the file blspy-0.2.1-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: blspy-0.2.1-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.48.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2.1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 6c645e834c951ed19194fc8c730203fec092d5133c58e71f14f186369c6d3aa5
MD5 cb46521d6c16c5504db126dda2790fad
BLAKE2b-256 2ebda53165801dd4b9b2b192a136cb864d7d504c19190d39f26350182e301536

See more details on using hashes here.

File details

Details for the file blspy-0.2.1-cp38-cp38-manylinux2014_aarch64.whl.

File metadata

  • Download URL: blspy-0.2.1-cp38-cp38-manylinux2014_aarch64.whl
  • Upload date:
  • Size: 686.7 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.48.0 CPython/3.8.2

File hashes

Hashes for blspy-0.2.1-cp38-cp38-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 037e9f0043156eb1719b58586276b9acd1ea4bd4a8b16268b87bdb4f79f56e55
MD5 86729bb97cb8cbdade6fa3777bc2ab9b
BLAKE2b-256 45bebfc3385aedf2a9da1d600a67eaccc3c3c73aa020105b3502fc6a0d0a5590

See more details on using hashes here.

File details

Details for the file blspy-0.2.1-cp38-cp38-manylinux2010_x86_64.whl.

File metadata

  • Download URL: blspy-0.2.1-cp38-cp38-manylinux2010_x86_64.whl
  • Upload date:
  • Size: 787.9 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.23.0 setuptools/47.1.0 requests-toolbelt/0.9.1 tqdm/4.48.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2.1-cp38-cp38-manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 79ea165946a8bd652655f1c30e162a5dae3c82f06144a15e02faa1a5fbaddfec
MD5 f69d256046e1d8102ca9030659b6338b
BLAKE2b-256 f90b83ec5328acf3bdf84e14ee33b4cc12b601e37bd46cf219c826b7772b0a38

See more details on using hashes here.

File details

Details for the file blspy-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl.

File metadata

  • Download URL: blspy-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 640.5 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.48.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 9c0220f9d0715d9cbee28fe50e2421ea9983af59c627e8fedfe47b8158167f0d
MD5 9d413d3e4549353c4fb059add04fcc7e
BLAKE2b-256 af5c8deb5fa6e1c26126395d80fb9bccec8feb9a0d813e4e34ae27f6ed4c7016

See more details on using hashes here.

File details

Details for the file blspy-0.2.1-cp37-cp37m-win_amd64.whl.

File metadata

  • Download URL: blspy-0.2.1-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.48.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2.1-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 076126674bf785f5c5661a9055969d8ca41239152aa293b5c17aa281a346cf92
MD5 22fd2abee7886323022b2f44024de89d
BLAKE2b-256 c47e1f9d4c6b45a8b9e211040f2cd5cf86affe1067ff502719adcbb65e6b5a88

See more details on using hashes here.

File details

Details for the file blspy-0.2.1-cp37-cp37m-manylinux2014_aarch64.whl.

File metadata

  • Download URL: blspy-0.2.1-cp37-cp37m-manylinux2014_aarch64.whl
  • Upload date:
  • Size: 692.4 kB
  • Tags: CPython 3.7m
  • 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.48.0 CPython/3.8.2

File hashes

Hashes for blspy-0.2.1-cp37-cp37m-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 65adf1cb37ef4aa6ed44c8fb5c601a23a94397f46421bd076a87ae6a7b4ee39d
MD5 e9803d1f8a173379efe7a64d938e0b0f
BLAKE2b-256 c323eaa4b066d4d859a5ecd61476e4e7cbb63c0531d9817c7ff376fd59ef58e8

See more details on using hashes here.

File details

Details for the file blspy-0.2.1-cp37-cp37m-manylinux2010_x86_64.whl.

File metadata

  • Download URL: blspy-0.2.1-cp37-cp37m-manylinux2010_x86_64.whl
  • Upload date:
  • Size: 788.4 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.23.0 setuptools/47.1.0 requests-toolbelt/0.9.1 tqdm/4.48.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2.1-cp37-cp37m-manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 4c799b420a2b148da087801735a39ad52fa39cc11230f492f5925d55b0f82c90
MD5 b18f5adb2e8fff512ba7331cd009db76
BLAKE2b-256 1b6352290f321180b3d3660162b4c519e003e95385166721950e8a16262ae0ad

See more details on using hashes here.

File details

Details for the file blspy-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl.

File metadata

  • Download URL: blspy-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 634.3 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.48.0 CPython/3.7.8

File hashes

Hashes for blspy-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 5c90d3a69138d27edf99e38d5e1a3ac76cc7b9676e107bfe4e022e68b4fe98c7
MD5 6526d897be7866b29156d02d2d7b0ba7
BLAKE2b-256 5d6c83d09d7ef0e2aab87d97a7f66a42a362044f49f683b232f5ebc62dfa2582

See more details on using hashes here.

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