Dash - Reinventing Cryptocurrency
Go to file
Odysseas Gabrielides 02107450d0 Squashed 'src/dashbls/' changes from 795660db76..4e070243ae
4e070243ae chore: bump version to 1.3.3 (#99)
d93956254e ci: disable Go bindings CI for macos for now (#98)
ae40c5c86d Merge pull request #97 from PastaPastaPasta/refac/pybind-bump-2.13.6
e835ece935 refactor: bump pybind version to 2.13.6
eda5d6a402 chore: change of gmp source (#95)
61f95aa80e chore: cleanup 6.2.1 left overs (#96)
adbd094409 Merge pull request #92 from kwvg/darwin_gmp
062ee6726b Merge pull request #90 from UdjinM6/fix_aarch_arch
3538d8b033 fix: aarch64 is not supported, should set ARCH to RELIC_NONE
e27a62f4a2 revert: disable gmp if targeting darwin on aarch64 when on 'auto'
bb2fe6ee55 build: enforce minimum version of libgmp based on arch and platform
9832b7a132 build: replace deprecated macros `AC_PROG_CC_C99` and `AM_PROG_CC_C_O`
b2428718b9 Merge pull request #91 from UdjinM6/fix_macos_test_build
3ffa7fa2b6 chore: bump version to 1.3.2 (#94)
0f4efc9327 Merge pull request #88 from HashEngineering/feat/support-android
a181889489 fix: rust bindings build for macos (#89)
738d187359 fix: detect gmp via brew earlier
ce4d6a47b6 fix: install libtool
4fa46ccaff fix: use macos-latest for test build
69bdc1aac7 Merge pull request #85 from kwvg/debug
39791d4e31 build: print build options after configure
73106a0121 build: use `-mbranch-protection=bti` on supporting `aarch64` compilers
6a3c28f6ca build: use stricter `-Werror` when testing compile flags
7a1b227637 build: rename {`NO`}`WARN_CFLAGS` to {`NO`}`WARN_FLAGS`, use with C{++}
28bea63838 build: set {`NO`}`WARN_CFLAGS` flags if not overridden and uniformly
32c2f0f5f8 trivial: rename `CORE_CXXFLAGS` to `CORE_FLAGS`, use with C{++}
b630c2c323 build: append `HARDENED_FLAGS` to `AM_CFLAGS`
e6008148e4 trivial: rename `HARDENED_CXXFLAGS` to `HARDENED_FLAGS`
af0e3daef5 build: subsume `PI{C,E}_FLAGS` into `HARDENED_CXXFLAGS`
9ff8618a1b build: expand `--disable-optimizations` to include `-O0` and `-fwrapv`
3036b83181 build: expand `--enable-debug` to include `-O0`, `-ftrapv` and dbg info
c90d43d43b build: add check to see if `CFLAGS` has been overridden
2d77f7ae49 build: remove vestigial `LIBTOOL_{CXX,CPP,LD}FLAGS`, `HARDENED_CPPFLAGS`
883a098868 build: autodetect i?86 and arm as 32-bit
deb3269820 build: don't specify exact `{CPU_}ARCH` if optimizations are disabled
720d49a44b trivial: fix indentation for `want_backend` check
f9328320af build: use `easy` backend if optimizations are disabled unless specified
3687cd59e0 build: define new flag `--enable-optimizations`
f82bfee5dd build: ensure help string format matches Autotool defaults
d68920063e build: define arguments as `--enable-[term]` instead of `--disable-[term]`
7f41e7dd16 fix: support android
1c2fc79c19 feat(rust): allow to move G1 and G2 elements between threads (#87)
3540b8bbed feat: debug with data hex (#86)

git-subtree-dir: src/dashbls
git-subtree-split: 4e070243aed142bc458472f8807ab77527dd879a
2024-10-09 17:25:18 +03:00
.github/workflows Squashed 'src/dashbls/' changes from 795660db76..4e070243ae 2024-10-09 17:25:18 +03:00
build-aux/m4 Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
cmake_modules Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
depends Squashed 'src/dashbls/' changes from 22b066020c..9329803969 2023-03-16 16:34:17 +00:00
go-bindings Squashed 'src/dashbls/' changes from 66ee820fbc..22b066020c 2023-01-02 12:40:54 +05:30
include/dashbls Squashed 'src/dashbls/' changes from 9329803969..795660db76 2023-06-28 23:43:42 +03:00
js-bindings Squashed 'src/dashbls/' changes from 9329803969..795660db76 2023-06-28 23:43:42 +03:00
python-bindings Squashed 'src/dashbls/' changes from 795660db76..4e070243ae 2024-10-09 17:25:18 +03:00
python-impl Squashed 'src/dashbls/' changes from 9329803969..795660db76 2023-06-28 23:43:42 +03:00
rust-bindings Squashed 'src/dashbls/' changes from 795660db76..4e070243ae 2024-10-09 17:25:18 +03:00
src Squashed 'src/dashbls/' changes from 9329803969..795660db76 2023-06-28 23:43:42 +03:00
.clang-format Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
.flake8 Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
.gitignore Squashed 'src/dashbls/' changes from 9329803969..795660db76 2023-06-28 23:43:42 +03:00
apple.rust.deps.sh Squashed 'src/dashbls/' changes from 795660db76..4e070243ae 2024-10-09 17:25:18 +03:00
autogen.sh Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
CMakeLists.txt Squashed 'src/dashbls/' changes from 9329803969..795660db76 2023-06-28 23:43:42 +03:00
configure.ac Squashed 'src/dashbls/' changes from 795660db76..4e070243ae 2024-10-09 17:25:18 +03:00
emsdk_build.sh Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
js_build_docker.sh Squashed 'src/dashbls/' changes from 22b066020c..9329803969 2023-03-16 16:34:17 +00:00
js_build.sh Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
js_test.sh Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
lgtm.yml Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
LICENSE Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
Makefile.am Squashed 'src/dashbls/' changes from 795660db76..4e070243ae 2024-10-09 17:25:18 +03:00
Makefile.bench.include Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
Makefile.bls.include Squashed 'src/dashbls/' changes from 66ee820fbc..22b066020c 2023-01-02 12:40:54 +05:30
Makefile.mimalloc.include Squashed 'src/dashbls/' changes from 66ee820fbc..22b066020c 2023-01-02 12:40:54 +05:30
Makefile.relic.include Squashed 'src/dashbls/' changes from 795660db76..4e070243ae 2024-10-09 17:25:18 +03:00
Makefile.test.include Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
MANIFEST.in Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
mypi.ini Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
pyproject.toml Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
README.md Squashed 'src/dashbls/' content from commit 66ee820fbc 2022-12-30 00:59:17 +05:30
setjmp_patch.diff Squashed 'src/dashbls/' changes from 9329803969..795660db76 2023-06-28 23:43:42 +03:00
setup.py Squashed 'src/dashbls/' changes from 22b066020c..9329803969 2023-03-16 16:34:17 +00:00

BLS Signatures implementation

Build and Test C++, Javascript, and Python PyPI PyPI - Format GitHub

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

NOTE: THIS LIBRARY IS NOT YET FORMALLY REVIEWED FOR SECURITY

NOTE: THIS LIBRARY WAS SHIFTED TO THE IETF BLS SPECIFICATION ON 7/16/20

Implements BLS signatures with aggregation using relic toolkit for cryptographic primitives (pairings, EC, hashing) according to the IETF BLS RFC with these curve parameters for BLS12-381.

Features:

  • Non-interactive signature aggregation following IETF specification
  • Works on Windows, Mac, Linux, BSD
  • Efficient verification using Proof of Posssesion (only one pairing per distinct message)
  • Aggregate public keys and private keys
  • EIP-2333 key derivation (including unhardened BIP-32-like keys)
  • Key and signature serialization
  • Batch verification
  • Python bindings
  • Pure python bls12-381 and signatures
  • JavaScript bindings

Before you start

This library uses minimum public key sizes (MPL). A G2Element is a signature (96 bytes), and a G1Element is a public key (48 bytes). A private key is a 32 byte integer. There are three schemes: Basic, Augmented, and ProofOfPossession. Augmented should be enough for most use cases, and ProofOfPossession can be used where verification must be fast.

Import the library

#include "bls.hpp"
using namespace bls;

Creating keys and signatures

// Example seed, used to generate private key. Always use
// a secure RNG with sufficient entropy to generate a seed (at least 32 bytes).
vector<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};

PrivateKey sk = AugSchemeMPL().KeyGen(seed);
G1Element pk = sk.GetG1Element();

vector<uint8_t> message = {1, 2, 3, 4, 5};  // Message is passed in as a byte vector
G2Element signature = AugSchemeMPL().Sign(sk, message);

// Verify the signature
bool ok = AugSchemeMPL().Verify(pk, message, signature);

Serializing keys and signatures to bytes

vector<uint8_t> skBytes = sk.Serialize();
vector<uint8_t> pkBytes = pk.Serialize();
vector<uint8_t> signatureBytes = signature.Serialize();

cout << Util::HexStr(skBytes) << endl;    // 32 bytes printed in hex
cout << Util::HexStr(pkBytes) << endl;    // 48 bytes printed in hex
cout << Util::HexStr(signatureBytes) << endl;  // 96 bytes printed in hex

Loading keys and signatures from bytes

// Takes vector of 32 bytes
PrivateKey skc = PrivateKey::FromByteVector(skBytes);

// Takes vector of 48 bytes
pk = G1Element::FromByteVector(pkBytes);

// Takes vector of 96 bytes
signature = G2Element::FromByteVector(signatureBytes);

Create aggregate signatures

// Generate some more private keys
seed[0] = 1;
PrivateKey sk1 = AugSchemeMPL().KeyGen(seed);
seed[0] = 2;
PrivateKey sk2 = AugSchemeMPL().KeyGen(seed);
vector<uint8_t> message2 = {1, 2, 3, 4, 5, 6, 7};

// Generate first sig
G1Element pk1 = sk1.GetG1Element();
G2Element sig1 = AugSchemeMPL().Sign(sk1, message);

// Generate second sig
G1Element pk2 = sk2.GetG1Element();
G2Element sig2 = AugSchemeMPL().Sign(sk2, message2);

// Signatures can be non-interactively combined by anyone
G2Element aggSig = AugSchemeMPL().Aggregate({sig1, sig2});

ok = AugSchemeMPL().AggregateVerify({pk1, pk2}, {message, message2}, aggSig);

Arbitrary trees of aggregates

seed[0] = 3;
PrivateKey sk3 = AugSchemeMPL().KeyGen(seed);
G1Element pk3 = sk3.GetG1Element();
vector<uint8_t> message3 = {100, 2, 254, 88, 90, 45, 23};
G2Element sig3 = AugSchemeMPL().Sign(sk3, message3);


G2Element aggSigFinal = AugSchemeMPL().Aggregate({aggSig, sig3});
ok = AugSchemeMPL().AggregateVerify({pk1, pk2, pk3}, {message, message2, message3}, aggSigFinal);

Very fast verification with Proof of Possession scheme

// If the same message is signed, you can use Proof of Posession (PopScheme) for efficiency
// A proof of possession MUST be passed around with the PK to ensure security.

G2Element popSig1 = PopSchemeMPL().Sign(sk1, message);
G2Element popSig2 = PopSchemeMPL().Sign(sk2, message);
G2Element popSig3 = PopSchemeMPL().Sign(sk3, message);
G2Element pop1 = PopSchemeMPL().PopProve(sk1);
G2Element pop2 = PopSchemeMPL().PopProve(sk2);
G2Element pop3 = PopSchemeMPL().PopProve(sk3);

ok = PopSchemeMPL().PopVerify(pk1, pop1);
ok = PopSchemeMPL().PopVerify(pk2, pop2);
ok = PopSchemeMPL().PopVerify(pk3, pop3);
G2Element popSigAgg = PopSchemeMPL().Aggregate({popSig1, popSig2, popSig3});

ok = PopSchemeMPL().FastAggregateVerify({pk1, pk2, pk3}, message, popSigAgg);

// Aggregate public key, indistinguishable from a single public key
G1Element popAggPk = pk1 + pk2 + pk3;
ok = PopSchemeMPL().Verify(popAggPk, message, popSigAgg);

// Aggregate private keys
PrivateKey aggSk = PrivateKey::Aggregate({sk1, sk2, sk3});
ok = (PopSchemeMPL().Sign(aggSk, message) == popSigAgg);

HD keys using EIP-2333

// You can derive 'child' keys from any key, to create arbitrary trees. 4 byte indeces are used.
// Hardened (more secure, but no parent pk -> child pk)
PrivateKey masterSk = AugSchemeMPL().KeyGen(seed);
PrivateKey child = AugSchemeMPL().DeriveChildSk(masterSk, 152);
PrivateKey grandChild = AugSchemeMPL().DeriveChildSk(child, 952)

// Unhardened (less secure, but can go from parent pk -> child pk), BIP32 style
G1Element masterPk = masterSk.GetG1Element();
PrivateKey childU = AugSchemeMPL().DeriveChildSkUnhardened(masterSk, 22);
PrivateKey grandchildU = AugSchemeMPL().DeriveChildSkUnhardened(childU, 0);

G1Element childUPk = AugSchemeMPL().DeriveChildPkUnhardened(masterPk, 22);
G1Element grandchildUPk = AugSchemeMPL().DeriveChildPkUnhardened(childUPk, 0);

ok = (grandchildUPk == grandchildU.GetG1Element();

Build

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

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

Run tests

./build/src/runtest

Run benchmarks

./build/src/runbench

On a 3.5 GHz i7 Mac, verification takes about 1.1ms per signature, and signing takes 1.3ms.

g++ -Wl,-no_pie -std=c++11  -Ibls-signatures/depends/relic/include -Ibls-signatures/build/depends/relic/include -Ibls-signatures/src -L./bls-signatures/build/ -l bls yourapp.cpp

Notes on dependencies

We use Libsodium and have GMP as an optional dependency: libsodium gives secure memory allocation, and GMP speeds up the library by ~ 3x. MPIR is used on Windows via GitHub Actions instead. 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 channel of Chia's public Keybase channels.

Code style

  • Always use vector<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
  • Use SecAlloc and SecFree when handling secrets

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. MacOS ARM64 is supported but not automated due to a lack of M1 CI runners. See .github/workflows/build.yml. CMake uses FetchContent to download pybind11 for the Python bindings and relic from a chia relic forked repository for Windows. Building is then managed by cibuildwheel. Further installation is then available via pip install blspy e.g. The ci builds include GMP and a statically linked libsodium.

Contributing and workflow

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

The main 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 main/release version in preparation for a new chia-blockchain release. Please branch or fork main and then create a pull request to the main branch. Linear merging is enforced on main 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 IETF bls draft is followed. Test vectors can also be seen in the python and 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

Relic license

Relic is used with the Apache 2.0 license