Coder Social home page Coder Social logo

mattrglobal / bbs-signatures Goto Github PK

View Code? Open in Web Editor NEW
105.0 14.0 25.0 1.06 MB

An implementation of BBS+ signatures for node and browser environments

License: Apache License 2.0

Rust 29.32% TypeScript 61.88% JavaScript 5.99% Shell 2.81%
cryptography digital-signature zero-knowledge-proofs wasm nucleus assurance

bbs-signatures's Introduction

MATTR

bbs-signatures

npm-version npm-unstable-version Master Release codecov

This repository is the home to a performant multi-message digital signature algorithm implementation which supports deriving zero knowledge proofs that enable selective disclosure from the originally signed message set.

BBS+ Signatures are a digital signature algorithm originally born from the work on Short group signatures by Boneh, Boyen, and Shachum which was later improved on in Constant-Size Dynamic k-TAA as BBS+ and touched on again in section 4.3 in Anonymous Attestation Using the Strong Diffie Hellman Assumption Revisited .

BBS+ signatures require a pairing-friendly curve, this library includes support for BLS12-381.

BBS+ Signatures allow for multi-message signing whilst producing a single output signature. With a BBS signature, a proof of knowledge based proof can be produced where only some of the originally signed messages are revealed at the discretion of the prover.

For more details on the signature algorithm please refer to here.

Getting started

To use this package within your project simply run

npm install @mattrglobal/bbs-signatures

Or with Yarn

yarn add @mattrglobal/bbs-signatures

Environment Support

This library includes a couple of features to ensure the most performant implementation of BBS is running in a execution environment. The order of selection is the following.

  1. If in a node js based environment and the optional dependency of @mattrglobal/node-bbs-signatures is installed use this.
  2. If in an environment that supports Web Assembly use this.

Note Please refer to running the benchmarks below where you can compare these different implementations, the differences are very notable.

Note To force the usage of a particular environment set the BBS_SIGNATURES_MODE environment variable to one of the following values

Note Previous releases of this library supported an asm.js compilation for usage in react native environments, however this has been deprecated due to performance issues.

Usage

See the sample directory for a runnable demo's.

The following is a short sample on how to use the API

import {
  generateBls12381G2KeyPair,
  blsSign,
  blsVerify,
  blsCreateProof,
  blsVerifyProof,
} from "@mattrglobal/bbs-signatures";

//Generate a new key pair
const keyPair = await generateBls12381G2KeyPair();

//Set of messages we wish to sign
const messages = [
  Uint8Array.from(Buffer.from("message1", "utf-8")),
  Uint8Array.from(Buffer.from("message2", "utf-8")),
];

//Create the signature
const signature = await blsSign({
  keyPair,
  messages: messages,
});

//Verify the signature
const isVerified = await blsVerify({
  publicKey: keyPair.publicKey,
  messages: messages,
  signature,
});

//Derive a proof from the signature revealing the first message
const proof = await blsCreateProof({
  signature,
  publicKey: keyPair.publicKey,
  messages,
  nonce: Uint8Array.from(Buffer.from("nonce", "utf8")),
  revealed: [0],
});

//Verify the created proof
const isProofVerified = await blsVerifyProof({
  proof,
  publicKey: keyPair.publicKey,
  messages: messages.slice(0, 1),
  nonce: Uint8Array.from(Buffer.from("nonce", "utf8")),
});

Element Size

Within a digital signature there are several elements for which it is useful to know the size, the following table outlines the general equation for calculating element sizes in relation to BBS+ signatures as it is dependent on the pairing friendly curve used.

Element Size Equation
Private Key F
Public Key G2
Signature G1 + 2*F
Proof 5*G1 + (4 + no_of_hidden_messages)*F
  • F A field element
  • G1 A point in the field of G1
  • G2 A point in the field of G2
  • no_of_hidden_messages The number of the hidden messages

This library includes specific support for BLS12-381 keys with BBS+ signatures and hence gives rise to the following concrete sizes

Element Size with BLS12-381
Private Key 32 Bytes
Public Key 96 Bytes
Signature 112 Bytes
Proof 368 + (no_of_hidden_messages)*32 Bytes

Getting started as a contributor

The following describes how to get started as a contributor to this project

Prerequisites

The following is a list of dependencies you must install to build and contribute to this project

For more details see our contribution guidelines

Install

To install the package dependencies run:

yarn install --frozen-lockfile

Build

To build the project for debug run:

yarn build

Test

To run the all test in the project run:

yarn test

To run just the tests for a node environment using the native node module of @mattrglobal-node-bbs-signatures run:

yarn test:node

To run just the tests for a node environment using the wasm module run:

yarn test:wasm

To run just the tests for a browser environment run:

yarn test:browser

Benchmark

To benchmark the implementation locally in a node environment using the native node module of @mattrglobal-node-bbs-signatures run:

yarn benchmark:node

To benchmark the implementation locally in a node environment using the wasm module run:

yarn benchmark:wasm

Dependencies

This library uses the bbs rust crate for the implementation of BBS+ signatures and BLS12-381 which is then wrapped and exposed in javascript/typescript using Web Assembly.

Security Policy

Please see our security policy for additional details about responsible disclosure of security related issues.

Relevant References

For those interested in more details, you might find the following resources helpful


Copyright © MATTR Limited. Some rights reserved.
“MATTR” is a trademark of MATTR Limited, registered in New Zealand and other countries.

bbs-signatures's People

Contributors

afonsobarracha avatar anton-iskryzhytskyi avatar benliumattr avatar caleb-mattr avatar dependabot[bot] avatar diogo-sousa-mattr avatar haardikk21 avatar jhill-mattr avatar kdenhartog avatar kenhuang avatar kirill-ivanov-mattr avatar liam-tait avatar margarytakolomiyets avatar mate-from-mattr avatar mikelodder7 avatar pablodenadai avatar petermetz avatar tplooker avatar wayne-shih avatar zedmattr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bbs-signatures's Issues

"Allocation failed - process out of memory" on Apple Silicon (aka M1)

I am running the library on an Apple Silicon (aka M1) MacBookPro and receive the subject error.

Steps to reproduce (a series of commands in shell):

$ node -p "process.arch + ' ' + process.platform + ' ' + process.version"
arm64 darwin v14.16.0

$ mkdir bbs-expt
$ cd $_
$ npm init -y
Wrote to /Users/[REDACTED]/dev/expt/bbs-expt/package.json:

{
  "name": "bbs-expt",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
$ npm i @mattrglobal/bbs-signatures

[NPM OUTPUT GOES HERE]

$ echo "require('@mattrglobal/bbs-signatures')" > index.js
$ node index.js

This results in node process crash with the following output:

(node:32546) Warning: Accessing non-existent property 'abort' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)

<--- Last few GCs --->

[32546:0x150008000]      125 ms: Scavenge 10.0 (11.7) -> 9.7 (12.4) MB, 0.4 / 0.0 ms  (average mu = 1.000, current mu = 1.000) allocation failure


<--- JS stacktrace --->

FATAL ERROR: wasm code commit Allocation failed - process out of memory
 1: 0x1044310cc node::Abort() [/opt/homebrew/opt/node@14/bin/node]
 2: 0x10443124c std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string<std::nullptr_t>(char const*) [/opt/homebrew/opt/node@14/bin/node]
 3: 0x104531448 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/opt/homebrew/opt/node@14/bin/node]
 4: 0x1045313dc v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/opt/homebrew/opt/node@14/bin/node]
 5: 0x1049a42e4 v8::internal::wasm::WasmCodeAllocator::AllocateForCodeInRegion(v8::internal::wasm::NativeModule*, unsigned long, v8::base::AddressRegion, v8::internal::wasm::WasmCodeAllocator::OptionalLock const&) [/opt/homebrew/opt/node@14/bin/node]
 6: 0x1049a4de8 v8::internal::wasm::NativeModule::CreateEmptyJumpTableInRegion(int, v8::base::AddressRegion, v8::internal::wasm::WasmCodeAllocator::OptionalLock const&) [/opt/homebrew/opt/node@14/bin/node]
 7: 0x1049a3d3c v8::internal::wasm::NativeModule::AddCodeSpace(v8::base::AddressRegion, v8::internal::wasm::WasmCodeAllocator::OptionalLock const&) [/opt/homebrew/opt/node@14/bin/node]
 8: 0x1049a4c04 v8::internal::wasm::NativeModule::NativeModule(v8::internal::wasm::WasmEngine*, v8::internal::wasm::WasmFeatures const&, v8::internal::VirtualMemory, std::__1::shared_ptr<v8::internal::wasm::WasmModule const>, std::__1::shared_ptr<v8::internal::Counters>, std::__1::shared_ptr<v8::internal::wasm::NativeModule>*) [/opt/homebrew/opt/node@14/bin/node]
 9: 0x1049a6c18 v8::internal::wasm::WasmCodeManager::NewNativeModule(v8::internal::wasm::WasmEngine*, v8::internal::Isolate*, v8::internal::wasm::WasmFeatures const&, unsigned long, std::__1::shared_ptr<v8::internal::wasm::WasmModule const>) [/opt/homebrew/opt/node@14/bin/node]
10: 0x1049b1af4 v8::internal::wasm::WasmEngine::NewNativeModule(v8::internal::Isolate*, v8::internal::wasm::WasmFeatures const&, std::__1::shared_ptr<v8::internal::wasm::WasmModule const>, unsigned long) [/opt/homebrew/opt/node@14/bin/node]
11: 0x104987df0 v8::internal::wasm::AsyncCompileJob::CreateNativeModule(std::__1::shared_ptr<v8::internal::wasm::WasmModule const>, unsigned long) [/opt/homebrew/opt/node@14/bin/node]
12: 0x104987fa4 v8::internal::wasm::AsyncCompileJob::GetOrCreateNativeModule(std::__1::shared_ptr<v8::internal::wasm::WasmModule const>, unsigned long) [/opt/homebrew/opt/node@14/bin/node]
13: 0x10498ee3c v8::internal::wasm::AsyncCompileJob::PrepareAndStartCompile::RunInForeground(v8::internal::wasm::AsyncCompileJob*) [/opt/homebrew/opt/node@14/bin/node]
14: 0x10498ec68 v8::internal::wasm::AsyncCompileJob::CompileStep::Run(v8::internal::wasm::AsyncCompileJob*, bool) [/opt/homebrew/opt/node@14/bin/node]
15: 0x10498eb78 v8::internal::wasm::AsyncCompileJob::CompileTask::RunInternal() [/opt/homebrew/opt/node@14/bin/node]
16: 0x104484bb0 node::PerIsolatePlatformData::RunForegroundTask(std::__1::unique_ptr<v8::Task, std::__1::default_delete<v8::Task> >) [/opt/homebrew/opt/node@14/bin/node]
17: 0x104483ca4 node::PerIsolatePlatformData::FlushForegroundTasksInternal() [/opt/homebrew/opt/node@14/bin/node]
18: 0x104484d6c node::NodePlatform::DrainTasks(v8::Isolate*) [/opt/homebrew/opt/node@14/bin/node]
19: 0x104464cfc node::NodeMainInstance::Run() [/opt/homebrew/opt/node@14/bin/node]
20: 0x10440c800 node::Start(int, char**) [/opt/homebrew/opt/node@14/bin/node]
21: 0x195b1df34 start [/usr/lib/system/libdyld.dylib]
[1]    32546 abort      node index.js

However, doing the same with the latest Node.js (v15.12.0) works well (assuming the files from above are still in place):

$ node -p "process.arch + ' ' + process.platform + ' ' + process.version"
arm64 darwin v15.12.0

$ node index.js
(node:32587) Warning: Accessing non-existent property 'abort' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)

$ node --trace-warnings index.js
(node:32591) Warning: Accessing non-existent property 'abort' of module exports inside circular dependency
    at emitCircularRequireWarning (node:internal/modules/cjs/loader:698:11)
    at Object.get (node:internal/modules/cjs/loader:712:5)
    at asmFunc (/Users/[REDACTED]/dev/expt/bbs-expt/node_modules/@mattrglobal/bbs-signatures/lib/wasm_asm.js:95:18)
    at Object.<anonymous> (/Users/[REDACTED]/dev/expt/bbs-expt/node_modules/@mattrglobal/bbs-signatures/lib/wasm_asm.js:184429:18)
    at Module._compile (node:internal/modules/cjs/loader:1092:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1121:10)
    at Module.load (node:internal/modules/cjs/loader:972:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Module.require (node:internal/modules/cjs/loader:996:19)
    at require (node:internal/modules/cjs/helpers:92:18)

Any ideas, if this could be fixed for Node v14?
Also what about the non-existing property issue?

Investigate why tests have to be run in node base jest environment

jest's default testing environment is jsdom, however when the tests are run for either asm.js or wasm in this environment using

yarn test:asm

OR

yarn test:wasm

errors such as the below are reported.

asm

TypeError: abort is not a function

wasm

RuntimeError: unreachable

To reproduce remove the testEnvironment: "node" from ./jest.config.js and run the tests.

Node < 14 spits circular dependency warning

I use this lib through transmutes "@transmute/did-key-bls12381". All I do is a simple generate a key. But upgrading my node version to run the test I get these warnings.
Screenshot 2021-05-20 at 18 16 04

Have you guys seen it before? Does not exist on 12.22.
Does this make sense to you guys?

I do guess this warning comes out of this lib as it is the only mentioned in the stacktrace

Some sources of the error is found here: nodejs/node#32987

WASM invocation in chromium browsers rolling back to ASM.js

When running this library in certain browsers, the following error is being reported.

Screen Shot 2020-11-21 at 1 48 33 PM

Impact is that the ASM.js rollback is being used instead of WASM which has a serious impact on performance.

Browsers tested (x indicates the occurrence of the issue)

[x] Brave
[x] Chrome
[ ] Safari
[ ] Firefox

TypeScript error: Cannot re-export a type when the '--isolatedModules' flag is provided

I tried to use it in react but i get this error:

TypeScript error in /Users/tec2/web/node_modules/@mattrglobal/bbs-signatures/lib/types/index.ts(14,10):
Cannot re-export a type when the '--isolatedModules' flag is provided.  TS1205
    12 |  */
    13 | 
  > 14 | export { BbsBlindSignContext } from "./BbsBlindSignContext";
       |          ^
    15 | export { BbsBlindSignContextRequest } from "./BbsBlindSignContextRequest";
    16 | export { BbsBlindSignRequest } from "./BbsBlindSignRequest";
    17 | export { BbsCreateProofRequest } from "./BbsCreateProofRequest";

Any ideas how to avoid this error?
Thank you in advance!

fix(sample/browser): TypeError: Reflect.get called on non-object

To reproduce:

  1. Clone my fork's branch (#48) that has the key pair generation function names fixed (otherwise the sample will stop working there)
  2. Run the browser samples as instructed by the readme file under ./sample/browser
  3. Observe the crash

Chrome Dev Tools Logs:

localhost/:1 Uncaught (in promise) Error(JsValue(TypeError: Reflect.get called on non-object
TypeError: Reflect.get called on non-object
    at Object.get (<anonymous>)
    at Module.eval (webpack:////home/peter/a/blockchain/bbs-signatures/pkg/index_bg.js?:644:23)
    at Module.eval (webpack:////home/peter/a/blockchain/bbs-signatures/pkg/index_bg.js?:451:22)
    at __wbg_get_2e96a823c1c5a5bd (http://localhost:8080/bbs-signatures.min.js:149:102)
    at js_sys::Reflect::get::hdb44b494eb45724a (http://localhost:8080/294ad96f2bf83bcad951.module.wasm:wasm-function[1000]:0x1b98b7)
    at js_sys::try_iter::hb9f6985e5939da27 (http://localhost:8080/294ad96f2bf83bcad951.module.wasm:wasm-function[260]:0x155380)
    at <serde_wasm_bindgen::de::Deserializer as serde::de::Deserializer>::deserialize_seq::h8a61401663b55dff (http://localhost:8080/294ad96f2bf83bcad951.module.wasm:wasm-function[335]:0x1665a5)
    at serde::de::impls::<impl serde::de::Deserialize for alloc::vec::Vec<T>>::deserialize::h1a24def40ef00233 (http://localhost:8080/294ad96f2bf83bcad951.module.wasm:wasm-function[5448]:0x240a27)
    at <core::marker::PhantomData<T> as serde::de::DeserializeSeed>::deserialize::hbf6636bd759ab427 (http://localhost:8080/294ad96f2bf83bcad951.module.wasm:wasm-function[5478]:0x24107b)
    at <serde_wasm_bindgen::de::SeqAccess as serde::de::SeqAccess>::next_element_seed::h2d960dcb668c8169 (http://localhost:8080/294ad96f2bf83bcad951.module.wasm:wasm-function[354]:0x16a3fc)))

With Dev Tools "Pause on Exception" this is where it goes sideways:

image

Add react-native-bbs-signatures as optional peer dependency

We've been working on a react native wrapper around the FFI interface that matches the interface of this library. We use it to expose the same functionlity in react native and leverage the jsonld-signatures-bbs library.

https://github.com/animo/react-native-bbs-signatures

Currently, however, we need to add overrides for all dependencies of @mattrglobal/bbs-signatures and map it to @animo-id/react-native-bbs-signatures. If we were to make @animo-id/react-native-bbs-signatures an optional peer dependency of this library and import it conditionally like is already done with node vs wasm, we wouldn't need any overrides anymore.

The package won't be installed by default and the user is still responsible for adding the dependency. It just adds support for the import in this library, meaning all packages that depend on this package (e.g. the bls12381-key-pair package) would automatically import the correct version.

We would still need to add the dependency to a react native project because autolinking only supports top-level packages declared in package.json, but it would make the setup easier.

Currently we have to add the following mapping to the package.json (depending whether you're using yarn/npm)

yarn

+   "resolutions": {
+     "@mattrglobal/bbs-signatures": "@animo-id/[email protected]",
+   }

npm

+   "overrides": {
+     "@mattrglobal/bbs-signatures": "@animo-id/[email protected]",
+   }

The resolution field says that any instance of @mattrglobal/bbs-signatures in any child dependency must be swapped
with @animo-id/react-native-bbs-signatures.

Add support for BLS signatures with BLS keys

In some cases for instance when a party would like to prove control of a key pair that will be used as the cryptographic binding to say a credential as documented here signatures offer an easy mechanism to do so and BLS signatures as a scheme are a good candidate to solve this problem

Consider removing the generated ES module

Currently because of limitations in how wasm-pack works with regards to generating WASM and the associated JS that is isomorphic to both browser and NodeJS. There is some messy post-build code required to create a CJS compatible version that will also run in NodeJS. The CJS based version is then what is predominantly used by most upstream libraries, hence keeping the ES module is perhaps redundant.

Investigate build pipeline error with wasm-opt

Running wasm-opt with the -Oz flag leads to a Segmentation fault meaning we are unable to build the most optimised version of WASM in our CI pipeline. Potential solutions include

  1. Change the OS that the build pipeline is running in.
  2. Monitor for future releases of wasm-opt that may rectify this issue.
  3. Try older releases of wasm-opt

Issue that might be of relevant here

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.