From 89ed2e68e732147f142cc117a51b505565a88e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Petruni=C4=87?= Date: Wed, 28 Aug 2019 17:14:30 +0200 Subject: [PATCH 1/5] fix ssz lint errors --- test/spec/spec-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/spec-tests b/test/spec/spec-tests index 7567342..15a1d85 160000 --- a/test/spec/spec-tests +++ b/test/spec/spec-tests @@ -1 +1 @@ -Subproject commit 7567342c966c4e020f6ab3889f93cedb65ea9bfe +Subproject commit 15a1d85125682d3ffc09a1ee9639f46c4a1653f6 From 57428df8ec5061bcc931944377bf4591782e7d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Petruni=C4=87?= Date: Wed, 28 Aug 2019 17:18:51 +0200 Subject: [PATCH 2/5] fix bls lint errors --- package.json | 2 +- src/@types/keccak256/index.d.ts | 2 +- src/helpers/g1point.ts | 130 ++++++++++++++++---------------- src/helpers/g2point.ts | 107 +++++++++++++------------- src/helpers/utils.ts | 8 +- src/index.ts | 13 +++- src/privateKey.ts | 51 +++++++------ src/publicKey.ts | 26 +++---- src/signature.ts | 16 ++-- src/web.ts | 5 +- 10 files changed, 183 insertions(+), 177 deletions(-) diff --git a/package.json b/package.json index 812e47c..fd73b1d 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "build-web": "webpack --mode production --entry ./lib/web.js --output ./dist/bls.min.js", "check-types": "tsc --noEmit", "lint": "eslint --ext .ts src/", - "lint-fix": "eslint --ext .ts src/ --fix", + "lint:fix": "eslint --ext .ts src/ --fix", "pretest": "yarn check-types", "prepublishOnly": "yarn build", "test:unit": "nyc --cache-dir .nyc_output/.cache -r lcov -e .ts mocha -r ./.babel-register 'test/unit/**/*.test.ts' && nyc report", diff --git a/src/@types/keccak256/index.d.ts b/src/@types/keccak256/index.d.ts index 75e63d9..ab9ee2a 100644 --- a/src/@types/keccak256/index.d.ts +++ b/src/@types/keccak256/index.d.ts @@ -1,4 +1,4 @@ -declare module 'keccak256' { +declare module "keccak256" { export default function hash(a: Buffer | (Buffer | string | number)[]): Buffer; diff --git a/src/helpers/g1point.ts b/src/helpers/g1point.ts index 8e087b4..9dcfa74 100644 --- a/src/helpers/g1point.ts +++ b/src/helpers/g1point.ts @@ -15,6 +15,71 @@ export class G1point { this.point = point; } + public static fromBytesCompressed(value: bytes48): G1point { + assert(value.length === FP_POINT_LENGTH, `Expected g1 compressed input to have ${FP_POINT_LENGTH} bytes`); + value = Buffer.from(value); + const aIn = (value[0] & (1 << 5)) != 0; + const bIn = (value[0] & (1 << 6)) != 0; + const cIn = (value[0] & (1 << 7)) != 0; + value[0] &= 31; + + if (!cIn) { + throw new Error("The serialised input does not have the C flag set."); + } + + const x = ctx.BIG.frombytearray(value, 0); + if (bIn) { + if (!aIn && x.iszilch()) { + // This is a correctly formed serialisation of infinity + return new G1point(new ctx.ECP()); + } else { + // The input is malformed + throw new Error( + "The serialised input has B flag set, but A flag is set, or X is non-zero."); + } + } + const modulus = getModulus(); + if (ctx.BIG.comp(modulus, x) <= 0) { + throw new Error("X coordinate is too large."); + } + + const point = new ctx.ECP(); + point.setx(x); + + if (point.is_infinity()) { + throw new Error("X coordinate is not on the curve."); + } + + // Did we get the right branch of the sqrt? + if (!point.is_infinity() && aIn != calculateYFlag(point.getY())) { + // We didn't: so choose the other branch of the sqrt. + const x = new ctx.FP(point.getX()); + const yneg = new ctx.FP(point.getY()); + yneg.neg(); + point.setxy(x.redc(), yneg.redc()); + } + + return new G1point(point); + } + + public static generator(): G1point { + return new G1point(ctx.ECP.generator()); + } + + public static random(): G1point { + let ecp: ECP; + do { + ecp = new ctx.ECP(); + ecp.setx( + ctx.BIG.frombytearray( + random.randomBuffer(FP_POINT_LENGTH), + 0 + ) + ); + } while (ecp.is_infinity()); + return new G1point(ecp); + } + public mul(value: BIG): G1point { const newPoint = this.point.mul(value); return new G1point(newPoint); @@ -54,69 +119,4 @@ export class G1point { output[0] |= flags; return output; } - - public static fromBytesCompressed(value: bytes48): G1point { - assert(value.length === FP_POINT_LENGTH, `Expected g1 compressed input to have ${FP_POINT_LENGTH} bytes`); - value = Buffer.from(value); - const aIn = (value[0] & (1 << 5)) != 0; - const bIn = (value[0] & (1 << 6)) != 0; - const cIn = (value[0] & (1 << 7)) != 0; - value[0] &= 31; - - if (!cIn) { - throw new Error("The serialised input does not have the C flag set."); - } - - const x = ctx.BIG.frombytearray(value, 0); - if (bIn) { - if (!aIn && x.iszilch()) { - // This is a correctly formed serialisation of infinity - return new G1point(new ctx.ECP()); - } else { - // The input is malformed - throw new Error( - "The serialised input has B flag set, but A flag is set, or X is non-zero."); - } - } - const modulus = getModulus(); - if (ctx.BIG.comp(modulus, x) <= 0) { - throw new Error("X coordinate is too large."); - } - - let point = new ctx.ECP(); - point.setx(x); - - if (point.is_infinity()) { - throw new Error("X coordinate is not on the curve."); - } - - // Did we get the right branch of the sqrt? - if (!point.is_infinity() && aIn != calculateYFlag(point.getY())) { - // We didn't: so choose the other branch of the sqrt. - const x = new ctx.FP(point.getX()); - const yneg = new ctx.FP(point.getY()); - yneg.neg(); - point.setxy(x.redc(), yneg.redc()) - } - - return new G1point(point); - } - - public static generator(): G1point { - return new G1point(ctx.ECP.generator()); - } - - public static random(): G1point { - let ecp: ECP; - do { - ecp = new ctx.ECP(); - ecp.setx( - ctx.BIG.frombytearray( - random.randomBuffer(FP_POINT_LENGTH), - 0 - ) - ) - } while (ecp.is_infinity()); - return new G1point(ecp); - } } diff --git a/src/helpers/g2point.ts b/src/helpers/g2point.ts index 2eaab98..a011fed 100644 --- a/src/helpers/g2point.ts +++ b/src/helpers/g2point.ts @@ -1,7 +1,7 @@ import {BIG} from "@chainsafe/milagro-crypto-js/src/big"; import {ECP2} from "@chainsafe/milagro-crypto-js/src/ecp2"; import {BLSDomain, bytes32, bytes96} from "../types"; -import { sha256 } from 'js-sha256'; +import {sha256} from "js-sha256"; import ctx from "../ctx"; import * as random from "secure-random"; import {calculateYFlag, getModulus, padLeft} from "./utils"; @@ -16,47 +16,6 @@ export class G2point { this.point = point; } - public add(other: G2point): G2point { - const sum = new ctx.ECP2(); - sum.add(this.point); - sum.add(other.point); - sum.affine(); - return new G2point(sum); - } - - public mul(value: BIG): G2point { - const newPoint = this.point.mul(value); - return new G2point(newPoint); - } - - public equal(other: G2point): boolean { - return this.point.equals(other.point); - } - - public getPoint(): ECP2 { - return this.point; - } - - public toBytesCompressed(): Buffer { - const xReBytes = Buffer.alloc(FP_POINT_LENGTH, 0); - const xImBytes = Buffer.alloc(FP_POINT_LENGTH, 0); - this.point.getX().getA().tobytearray(xReBytes, 0); - this.point.getX().getB().tobytearray(xImBytes, 0); - const c1 = true; - const b1 = this.point.is_infinity(); - const a1 = !b1 && calculateYFlag(this.point.getY().getB()); - - const flags = ((a1 ? 1 << 5 : 0) | (b1 ? 1 << 6 : 0) | (c1 ? 1 << 7 : 0)); - const mask = 31; - xImBytes[0] &= mask; - xImBytes[0] |= flags; - xReBytes[0] &= mask; - - return Buffer.concat([ - xImBytes, - xReBytes - ]); - } public static hashToG2(message: bytes32, domain: BLSDomain): G2point { const padding = Buffer.alloc(G2_HASH_PADDING, 0); @@ -66,7 +25,7 @@ export class G2point { Buffer.concat([ message, padLeft(domain, 8), - Buffer.from('01', 'hex') + Buffer.from("01", "hex") ]) )) ]); @@ -76,7 +35,7 @@ export class G2point { Buffer.concat([ message, padLeft(domain, 8), - Buffer.from('02', 'hex') + Buffer.from("02", "hex") ]) )) ]); @@ -89,13 +48,13 @@ export class G2point { xRe.add(one); xRe.norm(); point = new ctx.ECP2(); - point.setx(new ctx.FP2(xRe, xIm)) + point.setx(new ctx.FP2(xRe, xIm)); } return new G2point(G2point.scaleWithCofactor(G2point.normaliseY(point))); } public static fromCompressedBytes(value: bytes96): G2point { - assert(value.length === 2 * FP_POINT_LENGTH, 'Expected signature of 96 bytes'); + assert(value.length === 2 * FP_POINT_LENGTH, "Expected signature of 96 bytes"); value = Buffer.from(value); const xImBytes = value.slice(0, FP_POINT_LENGTH); const xReBytes = value.slice(FP_POINT_LENGTH); @@ -114,8 +73,8 @@ export class G2point { const xRe = ctx.BIG.frombytearray(xReBytes, 0); if (bIn) { if (!aIn - && xIm.iszilch() - && xRe.iszilch() ) { + && xIm.iszilch() + && xRe.iszilch() ) { // This is a correctly formed serialisation of infinity return new G2point(new ctx.ECP2()); } else { @@ -131,7 +90,7 @@ export class G2point { "The deserialised X real or imaginary coordinate is too large."); } - let point = new ctx.ECP2(); + const point = new ctx.ECP2(); point.setx(new ctx.FP2(xRe, xIm)); if(point.is_infinity()) { throw new Error("X coordinate is not on the curve."); @@ -189,7 +148,7 @@ export class G2point { 0 ) ) - ) + ); } while (point.is_infinity()); return new G2point(point); } @@ -235,14 +194,56 @@ export class G2point { const yNeg = new ctx.FP2(y); yNeg.neg(); if (ctx.BIG.comp(y.getB(), yNeg.getB()) < 0 - || ((ctx.BIG.comp(y.getB(), yNeg.getB()) == 0) - && ctx.BIG.comp(y.getA(), yNeg.getA()) < 0) + || ((ctx.BIG.comp(y.getB(), yNeg.getB()) == 0) + && ctx.BIG.comp(y.getA(), yNeg.getA()) < 0) ) { const newPoint = new ctx.ECP2(); newPoint.setxy(point.getX(), yNeg); - return newPoint + return newPoint; } else { return point; } } + + public add(other: G2point): G2point { + const sum = new ctx.ECP2(); + sum.add(this.point); + sum.add(other.point); + sum.affine(); + return new G2point(sum); + } + + public mul(value: BIG): G2point { + const newPoint = this.point.mul(value); + return new G2point(newPoint); + } + + public equal(other: G2point): boolean { + return this.point.equals(other.point); + } + + public getPoint(): ECP2 { + return this.point; + } + + public toBytesCompressed(): Buffer { + const xReBytes = Buffer.alloc(FP_POINT_LENGTH, 0); + const xImBytes = Buffer.alloc(FP_POINT_LENGTH, 0); + this.point.getX().getA().tobytearray(xReBytes, 0); + this.point.getX().getB().tobytearray(xImBytes, 0); + const c1 = true; + const b1 = this.point.is_infinity(); + const a1 = !b1 && calculateYFlag(this.point.getY().getB()); + + const flags = ((a1 ? 1 << 5 : 0) | (b1 ? 1 << 6 : 0) | (c1 ? 1 << 7 : 0)); + const mask = 31; + xImBytes[0] &= mask; + xImBytes[0] |= flags; + xReBytes[0] &= mask; + + return Buffer.concat([ + xImBytes, + xReBytes + ]); + } } diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts index 4bac7ba..64ad115 100644 --- a/src/helpers/utils.ts +++ b/src/helpers/utils.ts @@ -9,7 +9,7 @@ import ctx from "../ctx"; * @param length */ export function padLeft(source: Buffer, length: number): Buffer { - assert(source.length <= length, 'Given array must be smaller or equal to desired array size'); + assert(source.length <= length, "Given array must be smaller or equal to desired array size"); const result = Buffer.alloc(length, 0); source.copy(result, length - source.length); return result; @@ -19,11 +19,11 @@ export function padLeft(source: Buffer, length: number): Buffer { export function getModulus(): BIG { return ctx.BIG.frombytearray( Buffer.from( - '1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', - 'hex' + "1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", + "hex" ), 0 - ) + ); } export function calculateYFlag(yIm: BIG): boolean { diff --git a/src/index.ts b/src/index.ts index 31616a7..54f2a68 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,7 +49,7 @@ function sign(secretKey: BLSSecretKey, messageHash: bytes32, domain: BLSDomain): */ function aggregateSignatures(signatures: BLSSignature[]): BLSSignature { return signatures.map((signature): Signature => { - return Signature.fromCompressedBytes(signature) + return Signature.fromCompressedBytes(signature); }).reduce((previousValue, currentValue): Signature => { return previousValue.add(currentValue); }).toBytesCompressed(); @@ -64,7 +64,7 @@ function aggregatePubkeys(publicKeys: BLSPubkey[]): BLSPubkey { return new G1point(new ctx.ECP()).toBytesCompressed(); } return publicKeys.map((publicKey): G1point => { - return G1point.fromBytesCompressed(publicKey) + return G1point.fromBytesCompressed(publicKey); }).reduce((previousValue, currentValue): G1point => { return previousValue.add(currentValue); }).toBytesCompressed(); @@ -98,7 +98,12 @@ function verify(publicKey: BLSPubkey, messageHash: bytes32, signature: BLSSignat * @param signature * @param domain */ -function verifyMultiple(publicKeys: BLSPubkey[], messageHashes: bytes32[], signature: BLSSignature, domain: bytes8): boolean { +function verifyMultiple( + publicKeys: BLSPubkey[], + messageHashes: bytes32[], + signature: BLSSignature, + domain: bytes8 +): boolean { if(publicKeys.length === 0 || publicKeys.length != messageHashes.length) { return false; } @@ -129,4 +134,4 @@ export default { aggregatePubkeys, verify, verifyMultiple -} +}; diff --git a/src/privateKey.ts b/src/privateKey.ts index e99dba2..d2bfe90 100644 --- a/src/privateKey.ts +++ b/src/privateKey.ts @@ -15,6 +15,31 @@ export class PrivateKey { this.value = value; } + + public static fromBytes(bytes: Uint8Array): PrivateKey { + assert(bytes.length === SECRET_KEY_LENGTH, "Private key should have 32 bytes"); + const value = Buffer.from(bytes); + return new PrivateKey( + ctx.BIG.frombytearray( + padLeft( + value, + 48 + ), + 0 + ) + ); + } + + public static fromHexString(value: string): PrivateKey { + return PrivateKey.fromBytes( + Buffer.from(value.replace("0x", ""), "hex") + ); + } + + public static random(): PrivateKey { + return PrivateKey.fromBytes(random.randomBuffer(SECRET_KEY_LENGTH)); + } + public getValue(): BIG { return this.value; } @@ -34,31 +59,7 @@ export class PrivateKey { } public toHexString(): string { - return `0x${this.toBytes().toString('hex')}`; - } - - public static fromBytes(bytes: Uint8Array): PrivateKey { - assert(bytes.length === SECRET_KEY_LENGTH, 'Private key should have 32 bytes'); - const value = Buffer.from(bytes); - return new PrivateKey( - ctx.BIG.frombytearray( - padLeft( - value, - 48 - ), - 0 - ) - ) - } - - public static fromHexString(value: string): PrivateKey { - return PrivateKey.fromBytes( - Buffer.from(value.replace('0x', ''), 'hex') - ); - } - - public static random(): PrivateKey { - return PrivateKey.fromBytes(random.randomBuffer(SECRET_KEY_LENGTH)); + return `0x${this.toBytes().toString("hex")}`; } } diff --git a/src/publicKey.ts b/src/publicKey.ts index 6d734a1..d8bd967 100644 --- a/src/publicKey.ts +++ b/src/publicKey.ts @@ -9,19 +9,7 @@ export class PublicKey { public constructor(point: G1point) { this.point = point; } - - public getPoint(): G1point { - return this.point; - } - - public toBytesCompressed(): BLSPubkey { - return this.point.toBytesCompressed(); - } - - public toHexString(): string { - return `0x${this.toBytesCompressed().toString('hex')}`; - } - + public static fromPrivateKey(privateKey: PrivateKey): PublicKey { return new PublicKey( G1point.generator().mul(privateKey.getValue()) @@ -33,4 +21,16 @@ export class PublicKey { G1point.fromBytesCompressed(publicKey) ); } + + public getPoint(): G1point { + return this.point; + } + + public toBytesCompressed(): BLSPubkey { + return this.point.toBytesCompressed(); + } + + public toHexString(): string { + return `0x${this.toBytesCompressed().toString("hex")}`; + } } diff --git a/src/signature.ts b/src/signature.ts index 89dee16..00847ba 100644 --- a/src/signature.ts +++ b/src/signature.ts @@ -11,6 +11,14 @@ export class Signature { this.point = point; } + public static fromCompressedBytes(signature: BLSSignature): Signature { + assert( + signature.length === 2 * FP_POINT_LENGTH, + `Signature must have ${2 * FP_POINT_LENGTH} bytes` + ); + return new Signature(G2point.fromCompressedBytes(signature)); + } + public add(other: Signature): Signature { return new Signature( this.point.add(other.point) @@ -24,12 +32,4 @@ export class Signature { public toBytesCompressed(): BLSSignature { return this.point.toBytesCompressed(); } - - public static fromCompressedBytes(signature: BLSSignature): Signature { - assert( - signature.length === 2 * FP_POINT_LENGTH, - `Signature must have ${2 * FP_POINT_LENGTH} bytes` - ); - return new Signature(G2point.fromCompressedBytes(signature)); - } } diff --git a/src/web.ts b/src/web.ts index 08397b6..0217e53 100644 --- a/src/web.ts +++ b/src/web.ts @@ -1,8 +1,7 @@ -import bls from "./index" +import bls from "./index"; // eslint-disable-next-line @typescript-eslint/no-explicit-any -// @ts-ignore (function (window: any) { - window.bls = bls + window.bls = bls; // @ts-ignore })(window); From b8c262791a7ae60003a2130deb5482aca93d0962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Petruni=C4=87?= Date: Tue, 17 Sep 2019 21:02:32 +0200 Subject: [PATCH 3/5] fix ts errors --- src/helpers/g1point.ts | 46 +---------------------------------------- src/helpers/g2point.ts | 47 +++--------------------------------------- src/index.ts | 8 ++++++- src/privateKey.ts | 6 +++--- 4 files changed, 14 insertions(+), 93 deletions(-) diff --git a/src/helpers/g1point.ts b/src/helpers/g1point.ts index 9d832ca..7fd413c 100644 --- a/src/helpers/g1point.ts +++ b/src/helpers/g1point.ts @@ -5,7 +5,7 @@ import assert from "assert"; import {calculateYFlag, getModulus} from "./utils"; import * as random from "secure-random"; import {FP_POINT_LENGTH} from "../constants"; -import {BLSPubkey, bytes48} from "@chainsafe/eth2.0-types"; +import {bytes48} from "@chainsafe/eth2.0-types"; export class G1point { @@ -28,10 +28,6 @@ export class G1point { return new G1point(sum); } - public addRaw(other: bytes48): G1point { - return this.add(G1point.fromBytesCompressed(other)); - } - public equal(other: G1point): boolean { return this.point.equals(other.point); } @@ -131,44 +127,4 @@ export class G1point { } while (ecp.is_infinity()); return new G1point(ecp); } - - public mul(value: BIG): G1point { - const newPoint = this.point.mul(value); - return new G1point(newPoint); - } - - public add(other: G1point): G1point { - const sum = new ctx.ECP(); - sum.add(this.point); - sum.add(other.point); - sum.affine(); - return new G1point(sum); - } - - public equal(other: G1point): boolean { - return this.point.equals(other.point); - } - - public toBytes(): bytes48 { - const buffer = Buffer.alloc(FP_POINT_LENGTH, 0); - this.point.getX().tobytearray(buffer, 0); - return buffer; - } - - public getPoint(): ECP { - return this.point; - } - - public toBytesCompressed(): bytes48 { - const output = this.toBytes(); - const c = true; - const b = this.point.is_infinity(); - const a = !b && calculateYFlag(this.point.getY()); - - const flags = ((a ? 1 << 5 : 0) | (b ? 1 << 6 : 0) | (c ? 1 << 7 : 0)); - const mask = 31; - output[0] &= mask; - output[0] |= flags; - return output; - } } diff --git a/src/helpers/g2point.ts b/src/helpers/g2point.ts index e546288..5489d6a 100644 --- a/src/helpers/g2point.ts +++ b/src/helpers/g2point.ts @@ -1,6 +1,6 @@ import {BIG} from "@chainsafe/milagro-crypto-js/src/big"; import {ECP2} from "@chainsafe/milagro-crypto-js/src/ecp2"; -import {sha256} from 'js-sha256'; +import {sha256} from "js-sha256"; import ctx from "../ctx"; import * as random from "secure-random"; import {calculateYFlag, getModulus, padLeft} from "./utils"; @@ -37,7 +37,7 @@ export class G2point { return this.point; } - public toBytesCompressed(): bytes48 { + public toBytesCompressed(): Buffer { const xReBytes = Buffer.alloc(FP_POINT_LENGTH, 0); const xImBytes = Buffer.alloc(FP_POINT_LENGTH, 0); this.point.getX().getA().tobytearray(xReBytes, 0); @@ -95,7 +95,7 @@ export class G2point { } public static fromCompressedBytes(value: bytes48): G2point { - assert(value.length === 2 * FP_POINT_LENGTH, 'Expected signature of 96 bytes'); + assert(value.length === 2 * FP_POINT_LENGTH, "Expected signature of 96 bytes"); value = Buffer.from(value); const xImBytes = value.slice(0, FP_POINT_LENGTH); const xReBytes = value.slice(FP_POINT_LENGTH); @@ -246,45 +246,4 @@ export class G2point { } } - public add(other: G2point): G2point { - const sum = new ctx.ECP2(); - sum.add(this.point); - sum.add(other.point); - sum.affine(); - return new G2point(sum); - } - - public mul(value: BIG): G2point { - const newPoint = this.point.mul(value); - return new G2point(newPoint); - } - - public equal(other: G2point): boolean { - return this.point.equals(other.point); - } - - public getPoint(): ECP2 { - return this.point; - } - - public toBytesCompressed(): Buffer { - const xReBytes = Buffer.alloc(FP_POINT_LENGTH, 0); - const xImBytes = Buffer.alloc(FP_POINT_LENGTH, 0); - this.point.getX().getA().tobytearray(xReBytes, 0); - this.point.getX().getB().tobytearray(xImBytes, 0); - const c1 = true; - const b1 = this.point.is_infinity(); - const a1 = !b1 && calculateYFlag(this.point.getY().getB()); - - const flags = ((a1 ? 1 << 5 : 0) | (b1 ? 1 << 6 : 0) | (c1 ? 1 << 7 : 0)); - const mask = 31; - xImBytes[0] &= mask; - xImBytes[0] |= flags; - xReBytes[0] &= mask; - - return Buffer.concat([ - xImBytes, - xReBytes - ]); - } } diff --git a/src/index.ts b/src/index.ts index df664fe..4cc35f4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -101,19 +101,25 @@ export function verifyMultiple(publicKeys: BLSPubkey[], messageHashes: Hash[], s const eCombined = new ctx.FP12(1); + // @ts-ignore const reduction = messageHashes.reduce((previous, current, index) => { + // @ts-ignore if(previous.hash && current.equals(previous.hash)) { return { hash: previous.hash, + // @ts-ignore publicKey: previous.publicKey ? + // @ts-ignore previous.publicKey.addRaw(publicKeys[index]) : G1point.fromBytesCompressed(publicKeys[index]), }; - } else if(!!previous.hash) { + } else if(previous.hash) { + // @ts-ignore const g2 = G2point.hashToG2(previous.hash, domain); eCombined.mul( ElipticCurvePairing.pair( + // @ts-ignore previous.publicKey, g2 ) diff --git a/src/privateKey.ts b/src/privateKey.ts index 329fe2d..4b9e6d1 100644 --- a/src/privateKey.ts +++ b/src/privateKey.ts @@ -34,11 +34,11 @@ export class PrivateKey { } public toHexString(): string { - return `0x${this.toBytes().toString('hex')}`; + return `0x${this.toBytes().toString("hex")}`; } public static fromBytes(bytes: Uint8Array): PrivateKey { - assert(bytes.length === SECRET_KEY_LENGTH, 'Private key should have 32 bytes'); + assert(bytes.length === SECRET_KEY_LENGTH, "Private key should have 32 bytes"); const value = Buffer.from(bytes); return new PrivateKey( ctx.BIG.frombytearray( @@ -53,7 +53,7 @@ export class PrivateKey { public static fromHexString(value: string): PrivateKey { return PrivateKey.fromBytes( - Buffer.from(value.replace('0x', ''), 'hex') + Buffer.from(value.replace("0x", ""), "hex") ); } From fe31dbc974cb2668fd93c7c1c7a3fe85c8f04b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Petruni=C4=87?= Date: Tue, 17 Sep 2019 21:05:13 +0200 Subject: [PATCH 4/5] fix bls lint --- src/helpers/g1point.ts | 80 ++++++++++++++++++++-------------------- src/helpers/g2point.ts | 83 +++++++++++++++++++++--------------------- src/index.ts | 7 +++- src/privateKey.ts | 43 +++++++++++----------- 4 files changed, 109 insertions(+), 104 deletions(-) diff --git a/src/helpers/g1point.ts b/src/helpers/g1point.ts index 7fd413c..3f7665b 100644 --- a/src/helpers/g1point.ts +++ b/src/helpers/g1point.ts @@ -15,46 +15,6 @@ export class G1point { this.point = point; } - public mul(value: BIG): G1point { - const newPoint = this.point.mul(value); - return new G1point(newPoint); - } - - public add(other: G1point): G1point { - const sum = new ctx.ECP(); - sum.add(this.point); - sum.add(other.point); - sum.affine(); - return new G1point(sum); - } - - public equal(other: G1point): boolean { - return this.point.equals(other.point); - } - - public toBytes(): bytes48 { - const buffer = Buffer.alloc(FP_POINT_LENGTH, 0); - this.point.getX().tobytearray(buffer, 0); - return buffer; - } - - public getPoint(): ECP { - return this.point; - } - - public toBytesCompressed(): bytes48 { - const output = this.toBytes(); - const c = true; - const b = this.point.is_infinity(); - const a = !b && calculateYFlag(this.point.getY()); - - const flags = ((a ? 1 << 5 : 0) | (b ? 1 << 6 : 0) | (c ? 1 << 7 : 0)); - const mask = 31; - output[0] &= mask; - output[0] |= flags; - return output; - } - public static fromBytesCompressed(value: bytes48): G1point { assert(value.length === FP_POINT_LENGTH, `Expected g1 compressed input to have ${FP_POINT_LENGTH} bytes`); value = Buffer.from(value); @@ -127,4 +87,44 @@ export class G1point { } while (ecp.is_infinity()); return new G1point(ecp); } + + public mul(value: BIG): G1point { + const newPoint = this.point.mul(value); + return new G1point(newPoint); + } + + public add(other: G1point): G1point { + const sum = new ctx.ECP(); + sum.add(this.point); + sum.add(other.point); + sum.affine(); + return new G1point(sum); + } + + public equal(other: G1point): boolean { + return this.point.equals(other.point); + } + + public toBytes(): bytes48 { + const buffer = Buffer.alloc(FP_POINT_LENGTH, 0); + this.point.getX().tobytearray(buffer, 0); + return buffer; + } + + public getPoint(): ECP { + return this.point; + } + + public toBytesCompressed(): bytes48 { + const output = this.toBytes(); + const c = true; + const b = this.point.is_infinity(); + const a = !b && calculateYFlag(this.point.getY()); + + const flags = ((a ? 1 << 5 : 0) | (b ? 1 << 6 : 0) | (c ? 1 << 7 : 0)); + const mask = 31; + output[0] &= mask; + output[0] |= flags; + return output; + } } diff --git a/src/helpers/g2point.ts b/src/helpers/g2point.ts index 5489d6a..c5f6421 100644 --- a/src/helpers/g2point.ts +++ b/src/helpers/g2point.ts @@ -16,47 +16,6 @@ export class G2point { this.point = point; } - public add(other: G2point): G2point { - const sum = new ctx.ECP2(); - sum.add(this.point); - sum.add(other.point); - sum.affine(); - return new G2point(sum); - } - - public mul(value: BIG): G2point { - const newPoint = this.point.mul(value); - return new G2point(newPoint); - } - - public equal(other: G2point): boolean { - return this.point.equals(other.point); - } - - public getPoint(): ECP2 { - return this.point; - } - - public toBytesCompressed(): Buffer { - const xReBytes = Buffer.alloc(FP_POINT_LENGTH, 0); - const xImBytes = Buffer.alloc(FP_POINT_LENGTH, 0); - this.point.getX().getA().tobytearray(xReBytes, 0); - this.point.getX().getB().tobytearray(xImBytes, 0); - const c1 = true; - const b1 = this.point.is_infinity(); - const a1 = !b1 && calculateYFlag(this.point.getY().getB()); - - const flags = ((a1 ? 1 << 5 : 0) | (b1 ? 1 << 6 : 0) | (c1 ? 1 << 7 : 0)); - const mask = 31; - xImBytes[0] &= mask; - xImBytes[0] |= flags; - xReBytes[0] &= mask; - - return Buffer.concat([ - xImBytes, - xReBytes - ]); - } public static hashToG2(message: Hash, domain: Domain): G2point { const padding = Buffer.alloc(G2_HASH_PADDING, 0); @@ -246,4 +205,46 @@ export class G2point { } } + public add(other: G2point): G2point { + const sum = new ctx.ECP2(); + sum.add(this.point); + sum.add(other.point); + sum.affine(); + return new G2point(sum); + } + + public mul(value: BIG): G2point { + const newPoint = this.point.mul(value); + return new G2point(newPoint); + } + + public equal(other: G2point): boolean { + return this.point.equals(other.point); + } + + public getPoint(): ECP2 { + return this.point; + } + + public toBytesCompressed(): Buffer { + const xReBytes = Buffer.alloc(FP_POINT_LENGTH, 0); + const xImBytes = Buffer.alloc(FP_POINT_LENGTH, 0); + this.point.getX().getA().tobytearray(xReBytes, 0); + this.point.getX().getB().tobytearray(xImBytes, 0); + const c1 = true; + const b1 = this.point.is_infinity(); + const a1 = !b1 && calculateYFlag(this.point.getY().getB()); + + const flags = ((a1 ? 1 << 5 : 0) | (b1 ? 1 << 6 : 0) | (c1 ? 1 << 7 : 0)); + const mask = 31; + xImBytes[0] &= mask; + xImBytes[0] |= flags; + xReBytes[0] &= mask; + + return Buffer.concat([ + xImBytes, + xReBytes + ]); + } + } diff --git a/src/index.ts b/src/index.ts index 4cc35f4..155275d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -91,7 +91,12 @@ export function verify(publicKey: BLSPubkey, messageHash: Hash, signature: BLSSi * @param signature * @param domain */ -export function verifyMultiple(publicKeys: BLSPubkey[], messageHashes: Hash[], signature: BLSSignature, domain: Domain): boolean { +export function verifyMultiple( + publicKeys: BLSPubkey[], + messageHashes: Hash[], + signature: BLSSignature, + domain: Domain +): boolean { if(publicKeys.length === 0 || publicKeys.length != messageHashes.length) { return false; } diff --git a/src/privateKey.ts b/src/privateKey.ts index 4b9e6d1..30c7f38 100644 --- a/src/privateKey.ts +++ b/src/privateKey.ts @@ -15,28 +15,6 @@ export class PrivateKey { this.value = value; } - public getValue(): BIG { - return this.value; - } - - public sign(message: G2point): G2point { - return message.mul(this.value); - } - - public signMessage(message: Hash, domain: Domain): G2point { - return G2point.hashToG2(message, domain).mul(this.value); - } - - public toBytes(): BLSSecretKey { - const buffer = Buffer.alloc(FP_POINT_LENGTH, 0); - this.value.tobytearray(buffer, 0); - return buffer.slice(FP_POINT_LENGTH - SECRET_KEY_LENGTH); - } - - public toHexString(): string { - return `0x${this.toBytes().toString("hex")}`; - } - public static fromBytes(bytes: Uint8Array): PrivateKey { assert(bytes.length === SECRET_KEY_LENGTH, "Private key should have 32 bytes"); const value = Buffer.from(bytes); @@ -61,4 +39,25 @@ export class PrivateKey { return PrivateKey.fromBytes(random.randomBuffer(SECRET_KEY_LENGTH)); } + public getValue(): BIG { + return this.value; + } + + public sign(message: G2point): G2point { + return message.mul(this.value); + } + + public signMessage(message: Hash, domain: Domain): G2point { + return G2point.hashToG2(message, domain).mul(this.value); + } + + public toBytes(): BLSSecretKey { + const buffer = Buffer.alloc(FP_POINT_LENGTH, 0); + this.value.tobytearray(buffer, 0); + return buffer.slice(FP_POINT_LENGTH - SECRET_KEY_LENGTH); + } + + public toHexString(): string { + return `0x${this.toBytes().toString("hex")}`; + } } From 4b488a097b217032fb3e53da40791ce1b48cf700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Petruni=C4=87?= Date: Tue, 17 Sep 2019 22:03:24 +0200 Subject: [PATCH 5/5] fix tests --- src/helpers/g1point.ts | 4 +++ test/unit/index.test.ts | 71 +++++++++++++++++++++-------------------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/helpers/g1point.ts b/src/helpers/g1point.ts index 3f7665b..538194a 100644 --- a/src/helpers/g1point.ts +++ b/src/helpers/g1point.ts @@ -101,6 +101,10 @@ export class G1point { return new G1point(sum); } + public addRaw(other: bytes48): G1point { + return this.add(G1point.fromBytesCompressed(other)); + } + public equal(other: G1point): boolean { return this.point.equals(other.point); } diff --git a/test/unit/index.test.ts b/test/unit/index.test.ts index ee819f2..1280932 100644 --- a/test/unit/index.test.ts +++ b/test/unit/index.test.ts @@ -1,19 +1,20 @@ import bls from "../../src"; import {Keypair} from "../../src/keypair"; -import {sha256} from 'js-sha256'; +import {sha256} from "js-sha256"; import {G2point} from "../../src/helpers/g2point"; import {expect} from "chai"; +import {describe, it} from "mocha"; -describe('test bls', function () { +describe("test bls", function () { - describe('aggregate pubkey', function () { - it('should aggregate empty array', function () { + describe("aggregate pubkey", function () { + it("should aggregate empty array", function () { expect(bls.aggregatePubkeys([])).to.not.throw; }); }); - describe('verify', function() { - it('should verify signature', () => { + describe("verify", function() { + it("should verify signature", () => { const keypair = Keypair.generate(); const messageHash = Buffer.from(sha256.arrayBuffer("Test")); const domain = Buffer.alloc(8, 1); @@ -30,7 +31,7 @@ describe('test bls', function () { }); - it('should not modify original pubkey when verifying', () => { + it("should not modify original pubkey when verifying", () => { const keypair = Keypair.generate(); const messageHash = Buffer.from(sha256.arrayBuffer("Test")); const domain = Buffer.alloc(8, 1); @@ -44,14 +45,14 @@ describe('test bls', function () { signature.toBytesCompressed(), domain ); - expect('0x' + pubKey.toString('hex')).to.be.equal(keypair.publicKey.toHexString()); + expect("0x" + pubKey.toString("hex")).to.be.equal(keypair.publicKey.toHexString()); }); - it('should fail verify empty signature', () => { + it("should fail verify empty signature", () => { const keypair = Keypair.generate(); const messageHash2 = Buffer.from(sha256.arrayBuffer("Test message2")); - const domain = Buffer.from("01", 'hex'); + const domain = Buffer.from("01", "hex"); const signature = Buffer.alloc(96); const result = bls.verify( keypair.publicKey.toBytesCompressed(), @@ -62,11 +63,11 @@ describe('test bls', function () { expect(result).to.be.false; }); - it('should fail verify signature of different message', () => { + it("should fail verify signature of different message", () => { const keypair = Keypair.generate(); const messageHash = Buffer.from(sha256.arrayBuffer("Test message")); const messageHash2 = Buffer.from(sha256.arrayBuffer("Test message2")); - const domain = Buffer.from("01", 'hex'); + const domain = Buffer.from("01", "hex"); const signature = keypair.privateKey.sign( G2point.hashToG2(messageHash, domain) ); @@ -79,11 +80,11 @@ describe('test bls', function () { expect(result).to.be.false; }); - it('should fail verify signature of different domain', () => { + it("should fail verify signature of different domain", () => { const keypair = Keypair.generate(); const messageHash = Buffer.from(sha256.arrayBuffer("Test message")); - const domain = Buffer.from("01", 'hex'); - const domain2 = Buffer.from("02", 'hex'); + const domain = Buffer.from("01", "hex"); + const domain2 = Buffer.from("02", "hex"); const signature = keypair.privateKey.sign( G2point.hashToG2(messageHash, domain) ); @@ -96,11 +97,11 @@ describe('test bls', function () { expect(result).to.be.false; }); - it('should fail verify signature signed by different key', () => { + it("should fail verify signature signed by different key", () => { const keypair = Keypair.generate(); const keypair2 = Keypair.generate(); const messageHash = Buffer.from(sha256.arrayBuffer("Test message")); - const domain = Buffer.from("01", 'hex'); + const domain = Buffer.from("01", "hex"); const signature = keypair.privateKey.sign( G2point.hashToG2(messageHash, domain) ); @@ -114,9 +115,9 @@ describe('test bls', function () { }); }); - describe('verify multiple', function() { + describe("verify multiple", function() { - it('should verify aggregated signatures', function () { + it("should verify aggregated signatures", function () { this.timeout(5000); @@ -127,8 +128,8 @@ describe('test bls', function () { const keypair3 = Keypair.generate(); const keypair4 = Keypair.generate(); - const message1 = Buffer.from("Test1", 'utf-8'); - const message2 = Buffer.from("Test2", 'utf-8'); + const message1 = Buffer.from("Test1", "utf-8"); + const message2 = Buffer.from("Test2", "utf-8"); const signature1 = keypair1.privateKey.signMessage(message1, domain); const signature2 = keypair2.privateKey.signMessage(message1, domain); @@ -162,7 +163,7 @@ describe('test bls', function () { expect(result).to.be.true; }); - it('should verify aggregated signatures - same message', function () { + it("should verify aggregated signatures - same message", function () { this.timeout(5000); @@ -173,7 +174,7 @@ describe('test bls', function () { const keypair3 = Keypair.generate(); const keypair4 = Keypair.generate(); - const message = Buffer.from("Test1", 'utf-8'); + const message = Buffer.from("Test1", "utf-8"); const signature1 = keypair1.privateKey.signMessage(message, domain); const signature2 = keypair2.privateKey.signMessage(message, domain); @@ -202,7 +203,7 @@ describe('test bls', function () { expect(result).to.be.true; }); - it('should fail to verify aggregated signatures - swapped messages', function () { + it("should fail to verify aggregated signatures - swapped messages", function () { this.timeout(5000); const domain = Buffer.alloc(8, 0); @@ -212,8 +213,8 @@ describe('test bls', function () { const keypair3 = Keypair.generate(); const keypair4 = Keypair.generate(); - const message1 = Buffer.from("Test1", 'utf-8'); - const message2 = Buffer.from("Test2", 'utf-8'); + const message1 = Buffer.from("Test1", "utf-8"); + const message2 = Buffer.from("Test2", "utf-8"); const signature1 = keypair1.privateKey.signMessage(message1, domain); const signature2 = keypair2.privateKey.signMessage(message1, domain); @@ -247,7 +248,7 @@ describe('test bls', function () { expect(result).to.be.false; }); - it('should fail to verify aggregated signatures - different pubkeys and messsages', () => { + it("should fail to verify aggregated signatures - different pubkeys and messsages", () => { const domain = Buffer.alloc(8, 0); @@ -256,8 +257,8 @@ describe('test bls', function () { const keypair3 = Keypair.generate(); const keypair4 = Keypair.generate(); - const message1 = Buffer.from("Test1", 'utf-8'); - const message2 = Buffer.from("Test2", 'utf-8'); + const message1 = Buffer.from("Test1", "utf-8"); + const message2 = Buffer.from("Test2", "utf-8"); const signature1 = keypair1.privateKey.signMessage(message1, domain); const signature2 = keypair2.privateKey.signMessage(message1, domain); @@ -287,7 +288,7 @@ describe('test bls', function () { expect(result).to.be.false; }); - it('should fail to verify aggregated signatures - different domain', () => { + it("should fail to verify aggregated signatures - different domain", () => { const domain = Buffer.alloc(8, 0); const domain2 = Buffer.alloc(8, 1); @@ -297,8 +298,8 @@ describe('test bls', function () { const keypair3 = Keypair.generate(); const keypair4 = Keypair.generate(); - const message1 = Buffer.from("Test1", 'utf-8'); - const message2 = Buffer.from("Test2", 'utf-8'); + const message1 = Buffer.from("Test1", "utf-8"); + const message2 = Buffer.from("Test2", "utf-8"); const signature1 = keypair1.privateKey.signMessage(message1, domain); const signature2 = keypair2.privateKey.signMessage(message1, domain); @@ -329,14 +330,14 @@ describe('test bls', function () { }); - it('should fail to verify aggregated signatures - no public keys', () => { + it("should fail to verify aggregated signatures - no public keys", () => { const domain = Buffer.alloc(8, 0); const signature = Buffer.alloc(96); - const message1 = Buffer.from("Test1", 'utf-8'); - const message2 = Buffer.from("Test2", 'utf-8'); + const message1 = Buffer.from("Test1", "utf-8"); + const message2 = Buffer.from("Test2", "utf-8"); const result = bls.verifyMultiple( [],