diff --git a/README.md b/README.md index 9dbd68d..e01a155 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,18 @@ Javascript library for BLS (Boneh-Lynn-Shacham) signatures and signature aggrega ## Usage ```ts -import {PrivateKey} from "@chainsafe/bls"; +import bls, {init} from "@chainsafe/bls"; -const secretKey = PrivateKey.fromKeygen(); -const publicKey = secretKey.toPublicKey(); -const message = new Uint8Array(32); +(async () => { + await init("herumi"); -const signature = secretKey.sign(message); -console.log("Is valid: ", signature.verify(publicKey, message)); + const secretKey = bls.PrivateKey.fromKeygen(); + const publicKey = secretKey.toPublicKey(); + const message = new Uint8Array(32); + + const signature = secretKey.sign(message); + console.log("Is valid: ", signature.verify(publicKey, message)); +})(); ``` ### Browser diff --git a/src/blst/index.ts b/src/blst/index.ts index f2093cf..75af81d 100644 --- a/src/blst/index.ts +++ b/src/blst/index.ts @@ -7,7 +7,7 @@ import {functionalInterfaceFactory} from "../functional"; export {PrivateKey, PublicKey, Signature}; -export async function initBLS(): Promise { +export async function init(): Promise { // Native bindings require no init() call } export function destroy(): void { @@ -20,7 +20,7 @@ export const bls: IBls = { Signature, ...functionalInterfaceFactory({PrivateKey, PublicKey, Signature}), - initBLS, + init, destroy, }; diff --git a/src/blst/privateKey.ts b/src/blst/privateKey.ts index c9d7a29..aeafde8 100644 --- a/src/blst/privateKey.ts +++ b/src/blst/privateKey.ts @@ -26,7 +26,7 @@ export class PrivateKey implements IPrivateKey { return new PrivateKey(sk); } - signMessage(message: Uint8Array): Signature { + sign(message: Uint8Array): Signature { return new Signature(this.value.sign(message)); } @@ -36,8 +36,8 @@ export class PrivateKey implements IPrivateKey { return new PublicKey(affine, jacobian); } - toBytes(): Buffer { - return Buffer.from(this.value.toBytes()); + toBytes(): Uint8Array { + return this.value.toBytes(); } toHex(): string { diff --git a/src/blst/publicKey.ts b/src/blst/publicKey.ts index ee28c5c..6301cf2 100644 --- a/src/blst/publicKey.ts +++ b/src/blst/publicKey.ts @@ -32,8 +32,8 @@ export class PublicKey implements IPublicKey { return signature.verify(this, message); } - toBytes(): Buffer { - return Buffer.from(this.affine.toBytes()); + toBytes(): Uint8Array { + return this.affine.toBytes(); } toHex(): string { diff --git a/src/blst/signature.ts b/src/blst/signature.ts index 5bad9d1..8316c96 100644 --- a/src/blst/signature.ts +++ b/src/blst/signature.ts @@ -39,8 +39,8 @@ export class Signature implements ISignature { ); } - toBytes(): Buffer { - return Buffer.from(this.affine.toBytes()); + toBytes(): Uint8Array { + return this.affine.toBytes(); } toHex(): string { diff --git a/src/constants.ts b/src/constants.ts index cf34046..1169bdd 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -3,5 +3,5 @@ export const SIGNATURE_LENGTH = 96; export const FP_POINT_LENGTH = 48; export const PUBLIC_KEY_LENGTH = FP_POINT_LENGTH; export const G2_HASH_PADDING = 16; -export const EMPTY_PUBLIC_KEY = Buffer.alloc(PUBLIC_KEY_LENGTH); -export const EMPTY_SIGNATURE = Buffer.alloc(SIGNATURE_LENGTH); +export const EMPTY_PUBLIC_KEY = Uint8Array.from(Buffer.alloc(PUBLIC_KEY_LENGTH)); +export const EMPTY_SIGNATURE = Uint8Array.from(Buffer.alloc(SIGNATURE_LENGTH)); diff --git a/src/functional.ts b/src/functional.ts index ddc84bc..7c7be12 100644 --- a/src/functional.ts +++ b/src/functional.ts @@ -13,18 +13,18 @@ export function functionalInterfaceFactory({ * @param secretKey * @param messageHash */ - function sign(secretKey: Uint8Array, messageHash: Uint8Array): Buffer { + function sign(secretKey: Uint8Array, messageHash: Uint8Array): Uint8Array { assert(secretKey, "secretKey is null or undefined"); assert(messageHash, "messageHash is null or undefined"); const privateKey = PrivateKey.fromBytes(secretKey); - return privateKey.signMessage(messageHash).toBytes(); + return privateKey.sign(messageHash).toBytes(); } /** * Compines all given signature into one. * @param signatures */ - function aggregateSignatures(signatures: Uint8Array[]): Buffer { + function aggregateSignatures(signatures: Uint8Array[]): Uint8Array { const agg = Signature.aggregate(signatures.map((p) => Signature.fromBytes(p))); return agg.toBytes(); } @@ -33,7 +33,7 @@ export function functionalInterfaceFactory({ * Combines all given public keys into single one * @param publicKeys */ - function aggregatePubkeys(publicKeys: Uint8Array[]): Buffer { + function aggregatePubkeys(publicKeys: Uint8Array[]): Uint8Array { const agg = PublicKey.aggregate(publicKeys.map((p) => PublicKey.fromBytes(p))); return agg.toBytes(); } diff --git a/src/herumi/context.ts b/src/herumi/context.ts index 0ac15fb..a35a59f 100644 --- a/src/herumi/context.ts +++ b/src/herumi/context.ts @@ -13,7 +13,7 @@ export async function setupBls(): Promise { } // Cache a promise for Bls instead of Bls to make sure it is initialized only once -export async function initBLS(): Promise { +export async function init(): Promise { if (!blsGlobalPromise) { blsGlobalPromise = setupBls(); } diff --git a/src/herumi/index.ts b/src/herumi/index.ts index 67b5688..ce40cfc 100644 --- a/src/herumi/index.ts +++ b/src/herumi/index.ts @@ -1,11 +1,11 @@ import {PrivateKey} from "./privateKey"; import {PublicKey} from "./publicKey"; import {Signature} from "./signature"; -import {initBLS, destroy} from "./context"; +import {init, destroy} from "./context"; import {IBls} from "../interface"; import {functionalInterfaceFactory} from "../functional"; -export {PrivateKey, PublicKey, Signature, initBLS, destroy}; +export {PrivateKey, PublicKey, Signature, init, destroy}; const bls: IBls = { PrivateKey, @@ -13,7 +13,7 @@ const bls: IBls = { Signature, ...functionalInterfaceFactory({PrivateKey, PublicKey, Signature}), - initBLS, + init, destroy, }; diff --git a/src/herumi/privateKey.ts b/src/herumi/privateKey.ts index 4e1a91e..9b8b8d6 100644 --- a/src/herumi/privateKey.ts +++ b/src/herumi/privateKey.ts @@ -19,7 +19,7 @@ export class PrivateKey implements IPrivateKey { assert(bytes.length === SECRET_KEY_LENGTH, "Private key should have 32 bytes"); const context = getContext(); const secretKey = new context.SecretKey(); - secretKey.deserialize(Buffer.from(bytes)); + secretKey.deserialize(bytes); return new PrivateKey(secretKey); } @@ -32,7 +32,7 @@ export class PrivateKey implements IPrivateKey { return this.fromBytes(sk); } - signMessage(message: Uint8Array): Signature { + sign(message: Uint8Array): Signature { return new Signature(this.value.sign(message)); } @@ -40,8 +40,8 @@ export class PrivateKey implements IPrivateKey { return new PublicKey(this.value.getPublicKey()); } - toBytes(): Buffer { - return Buffer.from(this.value.serialize()); + toBytes(): Uint8Array { + return this.value.serialize(); } toHex(): string { diff --git a/src/herumi/publicKey.ts b/src/herumi/publicKey.ts index d889eeb..79532c3 100644 --- a/src/herumi/publicKey.ts +++ b/src/herumi/publicKey.ts @@ -47,8 +47,8 @@ export class PublicKey implements IPublicKey { return this.value.verify(signature.value, messageHash); } - toBytes(): Buffer { - return Buffer.from(this.value.serialize()); + toBytes(): Uint8Array { + return this.value.serialize(); } toHex(): string { diff --git a/src/herumi/signature.ts b/src/herumi/signature.ts index 9198d43..13995c9 100644 --- a/src/herumi/signature.ts +++ b/src/herumi/signature.ts @@ -64,8 +64,8 @@ export class Signature implements ISignature { ); } - toBytes(): Buffer { - return Buffer.from(this.value.serialize()); + toBytes(): Uint8Array { + return this.value.serialize(); } toHex(): string { diff --git a/src/index.ts b/src/index.ts index 9a5d642..99476e6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,17 +3,13 @@ import blsHerumi from "./herumi"; export type Implementation = "herumi" | "blst-native"; -// This proxy makes sure a nice error is printed if BLS is used before init() -export let bls: IBls = new Proxy({} as IBls, { - get: function () { - throw Error("BLS not initialized, call init() before"); - }, -}); +// TODO: Use a Proxy for example to throw an error if it's not initialized yet +export let bls: IBls; async function getImplementation(impl: Implementation) { switch (impl) { case "herumi": - await blsHerumi.initBLS(); + await blsHerumi.init(); return blsHerumi; case "blst-native": diff --git a/src/interface.ts b/src/interface.ts index 0b4aebf..ee34ad2 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -15,14 +15,14 @@ export interface IBls { aggregate(signatures: ISignature[]): ISignature; }; - sign(secretKey: Uint8Array, messageHash: Uint8Array): Buffer; - aggregatePubkeys(publicKeys: Uint8Array[]): Buffer; - aggregateSignatures(signatures: Uint8Array[]): Buffer; + sign(secretKey: Uint8Array, messageHash: Uint8Array): Uint8Array; + aggregatePubkeys(publicKeys: Uint8Array[]): Uint8Array; + aggregateSignatures(signatures: Uint8Array[]): Uint8Array; verify(publicKey: Uint8Array, messageHash: Uint8Array, signature: Uint8Array): boolean; verifyAggregate(publicKeys: Uint8Array[], messageHash: Uint8Array, signature: Uint8Array): boolean; verifyMultiple(publicKeys: Uint8Array[], messageHashes: Uint8Array[], signature: Uint8Array): boolean; - initBLS(): Promise; + init(): Promise; destroy(): void; } @@ -32,12 +32,12 @@ export interface IKeypair { } export interface IPublicKey { - toBytes(): Buffer; + toBytes(): Uint8Array; toHex(): string; } export interface ISignature { - toBytes(): Buffer; + toBytes(): Uint8Array; toHex(): string; verify(publicKey: IPublicKey, message: Uint8Array): boolean; verifyAggregate(publicKeys: IPublicKey[], message: Uint8Array): boolean; @@ -46,7 +46,7 @@ export interface ISignature { export interface IPrivateKey { toPublicKey(): IPublicKey; - signMessage(message: Uint8Array): ISignature; - toBytes(): Buffer; + sign(message: Uint8Array): ISignature; + toBytes(): Uint8Array; toHex(): string; } diff --git a/test/benchmark/index.ts b/test/benchmark/index.ts index 18dc9ed..dd50290 100644 --- a/test/benchmark/index.ts +++ b/test/benchmark/index.ts @@ -4,7 +4,7 @@ import {runForAllImplementations} from "../switch"; import {IPublicKey, ISignature} from "../../src/interface"; runForAllImplementations(async (bls, implementation) => { - await bls.initBLS(); + await bls.init(); const aggCount = 30; @@ -17,7 +17,7 @@ runForAllImplementations(async (bls, implementation) => { const msg = randomMsg(); const sk = bls.PrivateKey.fromKeygen(); const pk = sk.toPublicKey(); - const sig = sk.signMessage(msg); + const sig = sk.sign(msg); return { input: {pk, msg, sig}, resultCheck: (valid) => valid === true, @@ -38,7 +38,7 @@ runForAllImplementations(async (bls, implementation) => { const dataArr = range(aggCount).map(() => { const sk = bls.PrivateKey.fromKeygen(); const pk = sk.toPublicKey(); - const sig = sk.signMessage(msg); + const sig = sk.sign(msg); return {pk, sig}; }); @@ -79,7 +79,7 @@ runForAllImplementations(async (bls, implementation) => { const msg = randomMsg(); const sigs = range(aggCount).map(() => { const sk = bls.PrivateKey.fromKeygen(); - return sk.signMessage(msg); + return sk.sign(msg); }); return { input: sigs, diff --git a/test/switch.ts b/test/switch.ts index 66a6f45..942f6ae 100644 --- a/test/switch.ts +++ b/test/switch.ts @@ -27,7 +27,7 @@ export function describeForAllImplementations(callback: (bls: IBls) => void): vo runForAllImplementations((bls, implementation) => { describe(implementation, () => { before(async () => { - await bls.initBLS(); + await bls.init(); }); callback(bls); diff --git a/test/unit/index.test.ts b/test/unit/index.test.ts index b7ef13b..68714ea 100644 --- a/test/unit/index.test.ts +++ b/test/unit/index.test.ts @@ -8,7 +8,7 @@ export function runIndexTests(bls: IBls): void { const sk = bls.PrivateKey.fromKeygen(); const pk = sk.toPublicKey(); const msg = randomMessage(); - const sig = sk.signMessage(msg); + const sig = sk.sign(msg); return {sk, pk, msg, sig}; } @@ -51,12 +51,7 @@ export function runIndexTests(bls: IBls): void { const msgs = getN(2, () => randomMessage()); const pks = sks.map((sk) => sk.toPublicKey()); - const sigs = [ - sks[0].signMessage(msgs[0]), - sks[1].signMessage(msgs[0]), - sks[2].signMessage(msgs[1]), - sks[3].signMessage(msgs[1]), - ]; + const sigs = [sks[0].sign(msgs[0]), sks[1].sign(msgs[0]), sks[2].sign(msgs[1]), sks[3].sign(msgs[1])]; const aggPubkeys = [ bls.aggregatePubkeys([pks[0], pks[1]].map((pk) => pk.toBytes())), @@ -74,7 +69,7 @@ export function runIndexTests(bls: IBls): void { const msg = randomMessage(); const sks = getN(n, () => bls.PrivateKey.fromKeygen()); const pks = sks.map((sk) => sk.toPublicKey()); - const sigs = sks.map((sk) => sk.signMessage(msg)); + const sigs = sks.map((sk) => sk.sign(msg)); const aggregateSignature = bls.aggregateSignatures(sigs.map((sig) => sig.toBytes())); diff --git a/test/unit/run-web-implementation.test.ts b/test/unit/run-web-implementation.test.ts index b70e9bd..159c0f2 100644 --- a/test/unit/run-web-implementation.test.ts +++ b/test/unit/run-web-implementation.test.ts @@ -11,7 +11,7 @@ describe("herumi", () => { before(async () => { // For consistency with describeForAllImplementations // eslint-disable-next-line import/no-named-as-default-member - await herumi.initBLS(); + await herumi.init(); }); runPrivateKeyTests(herumi); diff --git a/test/util.ts b/test/util.ts index e25f4b5..1ae5cc0 100644 --- a/test/util.ts +++ b/test/util.ts @@ -1,7 +1,7 @@ import crypto from "crypto"; -export function fromHexString(hex: string): Buffer { - return Buffer.from(hex.replace("0x", ""), "hex"); +export function fromHexString(hex: string): Uint8Array { + return Uint8Array.from(Buffer.from(hex.replace("0x", ""), "hex")); } export function toHexString(bytes: Buffer | Uint8Array): string {