-
Notifications
You must be signed in to change notification settings - Fork 213
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add simple build script * Add simple bindings * Changed WSIZE to 32 to make emscripten work (it's a 32-bit compiler); Added some bindings and tests for the bindings * Add simple bindings for the Signature class * Add a new helper to copy c++ vector<uin8_t> to js Buffer in order to avoid raw memory views, as they can lead to a data corruption; Modify CMake bindings config to make CMake working properly; * Add a new helper to copy c++ vector<uin8_t> to js Buffer in order to avoid raw memory views, as they can lead to a data corruption; Modify CMake bindings config to make CMake working properly; * Add bindings for the PublicKey and a test for the PrivateKey * Add test for PublicKey * Add aggregation methods for public and private keys * Reformat code a bit * Add more helpers for bns, byte arrays and vectors; Add AggregationInfo class; Separated helpers to header and implementation * Modify main cmake file to include specific emscripten instructions * Add some works on signature aggregation * Fixed cmake build for emscripten * Make signature aggregation work * Reformat code * Reformat bindings * Refactor helpers and wrappers * Revert main cmake * Add wrapper for extended private key * Add extended public key wrapper; Add extended private and public keys to bindings * Add ChainCode wrapper and bindings * Add initial typings * Add more ts typings; Add InsecureSignature wrapper and JS binding; * Refactored wrappers a bit * Add a base wrapper * Add simple readme * Fix typos in readme * Add license to js bindings * Make CMake copy js package files to the build dir; Make CMake to copy js tests to the build dir; Make CMake install npm dependencies after the build; Make tests to require lib from the parent dir * Modify readme a bit * Modify readme a bit * Modify readme a bit * Modify readme a bit * Modify readme a bit * Add repository to package.json * Add some content to threshold wrapper; Port thershold signature test * Add test for Threshold * Add tests for ExtendedPrivateKey, ExtendedPublicKey, ChainCode, add more tests for PrivateKey, fixed typings a bit * Update name in package.json * Add bundling memfile to bindings; Fix bindings readme; Bumped patch version * Reformat wrappers code * Apply README grammar fixes * Make lib interface to interact with Uint8Array instead of Buffer; Changed default compilation target to wasm instead of asmjs * Add information about deleting objects to README; Add .delete method to all objects in typings * Add browser tests * Mentioned firefox tests in Readme * Add simple test for typings * Add tests for typings * Add constants from bls classes * Add GROUP_ORDER constant * Fix cpplint errors * Fix readme grammar * Add bindings for DHKeyExchange * Remove relic headers from helpers
- Loading branch information
Showing
40 changed files
with
8,031 additions
and
3 deletions.
There are no files selected for viewing
This file contains 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 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 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 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 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.