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] 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);