This repository was archived by the owner on Jul 2, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 211
JS bindings #55
Merged
Merged
JS bindings #55
Changes from all commits
Commits
Show all changes
55 commits
Select commit
Hold shift + click to select a range
7f704bb
Add simple build script
antouhou 4dab6f6
Add simple bindings
antouhou b340986
Changed WSIZE to 32 to make emscripten work (it's a 32-bit compiler);…
antouhou a7d6895
Add simple bindings for the Signature class
antouhou 75e2832
Add a new helper to copy c++ vector<uin8_t> to js Buffer in order to …
antouhou 74d4bc2
Add a new helper to copy c++ vector<uin8_t> to js Buffer in order to …
antouhou 5912faa
Add bindings for the PublicKey and a test for the PrivateKey
antouhou 1a7f6df
Add test for PublicKey
antouhou 5e1fd99
Add aggregation methods for public and private keys
antouhou e9b66f6
Reformat code a bit
antouhou e07ab47
Add more helpers for bns, byte arrays and vectors; Add AggregationInf…
antouhou 3fc79d6
Modify main cmake file to include specific emscripten instructions
antouhou 6f5168d
Add some works on signature aggregation
antouhou e23ae74
Fixed cmake build for emscripten
antouhou 3dcb61f
Make signature aggregation work
antouhou 758716e
Reformat code
antouhou c149760
Reformat bindings
antouhou b4d97cb
Refactor helpers and wrappers
antouhou ef5d37d
Revert main cmake
antouhou 70f9520
Add wrapper for extended private key
antouhou b5c696c
Add extended public key wrapper; Add extended private and public keys…
antouhou 2366114
Add ChainCode wrapper and bindings
antouhou 93e388b
Add initial typings
antouhou aa0ca9a
Add more ts typings; Add InsecureSignature wrapper and JS binding;
antouhou 6c0a118
Refactored wrappers a bit
antouhou 5fb2cc9
Add a base wrapper
antouhou 2678b84
Add simple readme
antouhou b9c5960
Fix typos in readme
antouhou 4596601
Add license to js bindings
antouhou 5485a83
Make CMake copy js package files to the build dir; Make CMake to copy…
antouhou 207c95e
Modify readme a bit
antouhou 911c47c
Modify readme a bit
antouhou 4824d74
Modify readme a bit
antouhou 081c72a
Modify readme a bit
antouhou 94a5ed2
Modify readme a bit
antouhou 7d51e5e
Add repository to package.json
antouhou 7c51949
Add some content to threshold wrapper; Port thershold signature test
antouhou d6e4978
Add test for Threshold
antouhou ead3927
Add tests for ExtendedPrivateKey, ExtendedPublicKey, ChainCode, add m…
antouhou d545bd4
Update name in package.json
antouhou 9593c7d
Add bundling memfile to bindings; Fix bindings readme; Bumped patch v…
antouhou 1e443d0
Reformat wrappers code
antouhou 47a4537
Apply README grammar fixes
antouhou c7a6c2c
Make lib interface to interact with Uint8Array instead of Buffer; Cha…
antouhou 088a788
Add information about deleting objects to README; Add .delete method …
antouhou bfba8fe
Add browser tests
antouhou ea3f79d
Mentioned firefox tests in Readme
antouhou bb2949b
Add simple test for typings
antouhou 66ee882
Add tests for typings
antouhou 4f8ae05
Add constants from bls classes
antouhou a6cb154
Add GROUP_ORDER constant
antouhou 28a2499
Fix cpplint errors
antouhou 88c1f42
Fix readme grammar
antouhou 064ac45
Add bindings for DHKeyExchange
antouhou 690ef87
Remove relic headers from helpers
antouhou File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0 FATAL_ERROR) | ||
| set(CMAKE_CXX_STANDARD 11) | ||
|
|
||
| include_directories( | ||
| ${INCLUDE_DIRECTORIES} | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/relic/include | ||
| ${CMAKE_BINARY_DIR}/contrib/relic/include | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/catch | ||
| ) | ||
|
|
||
| file(GLOB_RECURSE WRAP_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/*.h) | ||
| file(GLOB_RECURSE WRAP_SRC ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/*.cpp) | ||
|
|
||
| add_executable(blsjs ${CMAKE_CURRENT_SOURCE_DIR}/jsbindings.cpp | ||
| ${WRAP_HEADERS} ${WRAP_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/helpers.h ${CMAKE_CURRENT_SOURCE_DIR}/helpers.cpp | ||
| ) | ||
| add_custom_target(install_npm_dependencies npm ci) | ||
| add_dependencies(blsjs install_npm_dependencies) | ||
|
|
||
| if (SODIUM_FOUND) | ||
| target_link_libraries(blsjs PRIVATE blstmp relic_s sodium) | ||
| else () | ||
| target_link_libraries(blsjs PRIVATE blstmp relic_s) | ||
| endif () | ||
|
|
||
| # Copy necessary files for the npm package | ||
| configure_file(${CMAKE_CURRENT_SOURCE_DIR}/package.json package.json COPYONLY) | ||
| configure_file(${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json package-lock.json COPYONLY) | ||
| configure_file(${CMAKE_CURRENT_SOURCE_DIR}/blsjs.d.ts blsjs.d.ts COPYONLY) | ||
| configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README.md README.md COPYONLY) | ||
|
|
||
| # Copy test files | ||
| file(GLOB JS_BINDINGS_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/tests/ ${CMAKE_CURRENT_SOURCE_DIR}/tests/*) | ||
| foreach(file ${JS_BINDINGS_TESTS}) | ||
| message(FILE ${file}) | ||
| configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tests/${file} tests/${file} COPYONLY) | ||
| endforeach() | ||
|
|
||
| set_target_properties(blsjs PROPERTIES LINK_FLAGS "--bind -s SINGLE_FILE=1 -s MODULARIZE_INSTANCE=1 -s BINARYEN_ASYNC_COMPILATION=0") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| ## bls-signatures | ||
|
|
||
| JavaScript library that implements BLS signatures with aggregation as in [Boneh, Drijvers, Neven 2018](https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html), using the relic toolkit for cryptographic primitives (pairings, EC, hashing). | ||
|
|
||
| This library is a JavaScript port of the [Chia Network's BLS lib](https://github.com/Chia-Network/bls-signatures). We also have typings, so you can use it with TypeScript too! | ||
|
|
||
| ### Usage | ||
|
|
||
| ```bash | ||
| npm i bls-signatures --save | ||
| ``` | ||
| ```javascript | ||
| const { PrivateKey } = require('bls-signatures'); | ||
| const privateKey = PrivateKey.fromSeed(Uint8Array.from([1,2,3])); | ||
| const sig = privateKey.sign(Uint8Array.from(Buffer.from("Hello world!"))); | ||
| const isValidSignature = sig.verify(); | ||
|
|
||
| if (isValidSignature) { | ||
| // Do stuff... | ||
| } | ||
|
|
||
| privateKey.delete(); | ||
| sig.delete(); | ||
| ``` | ||
|
|
||
| Please refer to the library's [typings](../../js-bindings/blsjs.d.ts) for detailed API information. Use cases can be found in the [original lib's readme](../../README.md). | ||
|
|
||
| __Important note on usage:__ Since this library is a WebAssembly port of the c++ library, JavaScript's automatic memory management isn't available. Please, delete all objects manually if they are not needed anymore by calling the delete method on them, as shown in the example above. | ||
|
|
||
| ### Build | ||
|
|
||
| Building requires Node.js (with npm) and [Emscripten](https://emscripten.org/docs/getting_started/downloads.html) to be installed. | ||
| The build process is the same as for the c++ lib, with one additional step: pass the Emscripten toolchain file as an option to CMake. | ||
| From the project root directory, run: | ||
| ``` | ||
| git submodule update --init --recursive | ||
| mkdir js_build | ||
| cd js_build | ||
| cmake ../ -DCMAKE_TOOLCHAIN_FILE={path_to_your_emscripten_installation}/emsdk/emscripten/{version}/cmake/Modules/Platform/Emscripten.cmake | ||
| cmake --build . -- | ||
| ``` | ||
|
|
||
| Run the build after any changes to the library, including readme and tests, as the library will be deployed from the build directory, and the build system copies all the files from the source dir. | ||
| ### Run tests | ||
| Tests are run in node.js and Firefox, therefore you need to install node.js and Firefox. | ||
| To run tests, build the library, then go to the `js_bindings` folder in the build directory and run | ||
| ```bash | ||
| npm test | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| export class PrivateKey { | ||
| static PRIVATE_KEY_SIZE: number; | ||
|
|
||
| static fromSeed(seed: Uint8Array): PrivateKey; | ||
|
|
||
| static fromBytes(bytes: Uint8Array, modOrder: boolean): PrivateKey; | ||
|
|
||
| static aggregate(privateKeys: PrivateKey[], publicKeys: PublicKey[]): PrivateKey; | ||
|
|
||
| static aggregateInsecure(privateKeys: PrivateKey[]): PrivateKey; | ||
|
|
||
| getPublicKey(): PublicKey; | ||
|
|
||
| serialize(): Uint8Array; | ||
|
|
||
| sign(message: Uint8Array): Signature; | ||
|
|
||
| signInsecure(message: Uint8Array): InsecureSignature; | ||
|
|
||
| signPrehashed(messageHash: Uint8Array): Signature; | ||
|
|
||
| delete(): void; | ||
| } | ||
|
|
||
| export class InsecureSignature { | ||
| static SIGNATURE_SIZE: number; | ||
|
|
||
| static fromBytes(bytes: Uint8Array); | ||
|
|
||
| static aggregate(signatures: InsecureSignature[]): InsecureSignature; | ||
|
|
||
| verify(hashes: Uint8Array[], pubKeys: PublicKey[]): boolean; | ||
|
|
||
| divideBy(insecureSignatures: InsecureSignature[]): InsecureSignature; | ||
|
|
||
| serialize(): Uint8Array; | ||
|
|
||
| delete(): void; | ||
| } | ||
|
|
||
| export class Signature { | ||
| static SIGNATURE_SIZE: number; | ||
|
|
||
| static fromBytes(bytes: Uint8Array): Signature; | ||
|
|
||
| static fromBytesAndAggregationInfo(bytes: Uint8Array, aggregationInfo: AggregationInfo): Signature; | ||
|
|
||
| static aggregateSigs(signatures: Signature[]): Signature; | ||
|
|
||
| serialize(): Uint8Array; | ||
|
|
||
| verify(): boolean; | ||
|
|
||
| getAggregationInfo(): AggregationInfo; | ||
|
|
||
| setAggregationInfo(aggregationInfo: AggregationInfo): void; | ||
|
|
||
| delete(): void; | ||
| } | ||
|
|
||
| export class PublicKey { | ||
| static PUBLIC_KEY_SIZE: number; | ||
|
|
||
| static fromBytes(bytes: Uint8Array): PublicKey; | ||
|
|
||
| static aggregate(publicKeys: PublicKey[]): PublicKey; | ||
|
|
||
| static aggregateInsecure(publicKeys: PublicKey[]): PublicKey; | ||
|
|
||
| getFingerprint(): number; | ||
|
|
||
| serialize(): Uint8Array; | ||
|
|
||
| delete(): void; | ||
| } | ||
|
|
||
| export class AggregationInfo { | ||
| static fromMsgHash(publicKey: PublicKey, messageHash: Uint8Array): AggregationInfo; | ||
|
|
||
| static fromMsg(publicKey: PublicKey, message: Uint8Array): AggregationInfo; | ||
|
|
||
| static fromBuffers(pubKeys: PublicKey[], msgHashes: Uint8Array[], exponents: Uint8Array[]): AggregationInfo; | ||
|
|
||
| getPublicKeys(): PublicKey[]; | ||
|
|
||
| getMessageHashes(): Uint8Array[]; | ||
|
|
||
| getExponents(): Uint8Array[]; | ||
|
|
||
| delete(): void; | ||
| } | ||
|
|
||
| export class ExtendedPrivateKey { | ||
| static EXTENDED_PRIVATE_KEY_SIZE: number; | ||
|
|
||
| static fromSeed(seed: Uint8Array): ExtendedPrivateKey; | ||
|
|
||
| static fromBytes(bytes: Uint8Array): ExtendedPrivateKey; | ||
|
|
||
| privateChild(index: number): ExtendedPrivateKey; | ||
|
|
||
| publicChild(index: number): ExtendedPublicKey; | ||
|
|
||
| getVersion(): number; | ||
|
|
||
| getDepth(): number; | ||
|
|
||
| getParentFingerprint(): number; | ||
|
|
||
| getChildNumber(): number; | ||
|
|
||
| getChainCode(): ChainCode; | ||
|
|
||
| getPrivateKey(): PrivateKey; | ||
|
|
||
| getPublicKey(): PublicKey; | ||
|
|
||
| getExtendedPublicKey(): ExtendedPublicKey; | ||
|
|
||
| serialize(): Uint8Array; | ||
|
|
||
| delete(): void; | ||
| } | ||
|
|
||
| export class ExtendedPublicKey { | ||
| static VERSION: number; | ||
| static EXTENDED_PUBLIC_KEY_SIZE: number; | ||
|
|
||
| static fromBytes(bytes: Uint8Array): ExtendedPublicKey; | ||
|
|
||
| publicChild(index: number): ExtendedPublicKey; | ||
|
|
||
| getVersion(): number; | ||
|
|
||
| getDepth(): number; | ||
|
|
||
| getParentFingerprint(): number; | ||
|
|
||
| getChildNumber(): number; | ||
|
|
||
| getPublicKey(): PublicKey; | ||
|
|
||
| getChainCode(): ChainCode; | ||
|
|
||
| serialize(): Uint8Array; | ||
|
|
||
| delete(): void; | ||
| } | ||
|
|
||
| export class ChainCode { | ||
| static CHAIN_CODE_SIZE: number; | ||
|
|
||
| static fromBytes(bytes: Uint8Array); | ||
|
|
||
| serialize(): Uint8Array; | ||
|
|
||
| delete(): void; | ||
| } | ||
|
|
||
| export namespace Threshold { | ||
| export function create(commitment: PublicKey[], secretFragments: PrivateKey[], threshold: number, playersCount: number): PrivateKey; | ||
|
|
||
| export function signWithCoefficient(sk: PrivateKey, message: Uint8Array, playerIndex: number, players: number[]): InsecureSignature; | ||
|
|
||
| export function aggregateUnitSigs(signatures: InsecureSignature[], message: Uint8Array, players: number[]): InsecureSignature; | ||
|
|
||
| export function verifySecretFragment(playerIndex: number, secretFragment: PrivateKey, commitment: PublicKey[], threshold: number): boolean; | ||
| } | ||
|
|
||
| export function DHKeyExchange(privateKey: PrivateKey, publicKey: PublicKey); | ||
|
|
||
| export const GROUP_ORDER: string; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| // Copyright 2018 Chia Network Inc | ||
|
|
||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
|
|
||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| #include "./helpers.h" | ||
|
|
||
| namespace helpers { | ||
| val toUint8Array(std::vector<uint8_t> vec) { | ||
| val arr = helpers::toJSArray<uint8_t>(vec); | ||
| return val::global("Uint8Array").call<val>("from", arr); | ||
| } | ||
|
|
||
| val toUint8Array(uint8_t *pointer, size_t data_size) { | ||
| std::vector<uint8_t> vec = toVector(pointer, data_size); | ||
| val buffer = toUint8Array(vec); | ||
| return buffer; | ||
| } | ||
|
|
||
| val toUint8Array(bn_t bn) { | ||
| std::vector<uint8_t> vec = toVector(bn); | ||
| val buffer = toUint8Array(vec); | ||
| return buffer; | ||
| } | ||
|
|
||
| std::vector<uint8_t> toVector(uint8_t *pointer, size_t data_size) { | ||
| std::vector<uint8_t> data; | ||
| data.reserve(data_size); | ||
| std::copy(pointer, pointer + data_size, std::back_inserter(data)); | ||
| return data; | ||
| } | ||
|
|
||
| std::vector<uint8_t> toVector(val jsUint8Array) { | ||
| auto l = jsUint8Array["length"].as<unsigned>(); | ||
| std::vector<uint8_t> vec; | ||
| for (unsigned i = 0; i < l; ++i) { | ||
| vec.push_back(jsUint8Array[i].as<uint8_t>()); | ||
| } | ||
| return vec; | ||
| } | ||
|
|
||
| std::vector<uint8_t> toVector(bn_t bn) { | ||
| uint8_t buf[bn_size_bin(bn)]; | ||
| bn_write_bin(buf, bn_size_bin(bn), bn); | ||
| std::vector<uint8_t> vec = helpers::toVector(buf, bn_size_bin(bn)); | ||
| return vec; | ||
| } | ||
|
|
||
| std::vector<std::vector<uint8_t>> jsBuffersArrayToVector(val buffersArray) { | ||
| auto l = buffersArray["length"].as<unsigned>(); | ||
| std::vector<std::vector<uint8_t>> vec; | ||
| for (unsigned i = 0; i < l; ++i) { | ||
| vec.push_back(toVector(buffersArray[i].as<val>())); | ||
| } | ||
| return vec; | ||
| } | ||
|
|
||
| std::vector<bn_t *> jsBuffersArrayToBnVector(val buffersArray) { | ||
| auto l = buffersArray["length"].as<unsigned>(); | ||
| std::vector<bn_t *> vec; | ||
| for (unsigned i = 0; i < l; ++i) { | ||
| bn_t data; | ||
| bn_new(data); | ||
| std::vector<uint8_t> bnVec = toVector(buffersArray[i]); | ||
| bn_read_bin(data, bnVec.data(), static_cast<int>(bnVec.size())); | ||
| bn_t *point = &data; | ||
| vec.push_back(point); | ||
| } | ||
| return vec; | ||
| } | ||
|
|
||
| val byteArraysVectorToJsBuffersArray(std::vector<uint8_t *> arraysVector, size_t element_size) { | ||
| auto vecSize = arraysVector.size(); | ||
| std::vector<val> valVector; | ||
| for (unsigned i = 0; i < vecSize; ++i) { | ||
| valVector.push_back(toUint8Array(arraysVector[i], element_size)); | ||
| } | ||
| val arr = helpers::toJSArray<val>(valVector); | ||
| return arr; | ||
| } | ||
| } // namespace helpers |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the browser compatibility like? We should add a note on that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will work in all browsers that support WASM, meaning Chrome, Firefox, Safari, Edge (Not IE, unfortunately). It is ~85% of currently existing devices: https://caniuse.com/#feat=wasm. Browsers support can be extended further by including
asm.jsbuild as well.asm.jshas broader support among older browsers (it's supported by all major browsers since the middle of 2013, except Safari, which is WASM-only). I'm not sure what is the best way to include both builds at the same time in one package, so I've added only WASM build. WASM has wider adoption (because of Safari), and has about 10x faster execution times.