Use isZeroUint8Array to check for empty bytes
This commit is contained in:
parent
6fe9b09a92
commit
32266dae20
|
@ -1,9 +1,10 @@
|
||||||
import * as blst from "@chainsafe/blst";
|
import * as blst from "@chainsafe/blst";
|
||||||
import {bytesToHex, hexToBytes, randomBytes} from "../helpers";
|
import {bytesToHex, hexToBytes, isZeroUint8Array, randomBytes} from "../helpers";
|
||||||
import {SECRET_KEY_LENGTH} from "../constants";
|
import {SECRET_KEY_LENGTH} from "../constants";
|
||||||
import {IPrivateKey} from "../interface";
|
import {IPrivateKey} from "../interface";
|
||||||
import {PublicKey} from "./publicKey";
|
import {PublicKey} from "./publicKey";
|
||||||
import {Signature} from "./signature";
|
import {Signature} from "./signature";
|
||||||
|
import {ZeroPrivateKeyError} from "../errors";
|
||||||
|
|
||||||
export class PrivateKey implements IPrivateKey {
|
export class PrivateKey implements IPrivateKey {
|
||||||
readonly value: blst.SecretKey;
|
readonly value: blst.SecretKey;
|
||||||
|
@ -13,6 +14,11 @@ export class PrivateKey implements IPrivateKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromBytes(bytes: Uint8Array): PrivateKey {
|
static fromBytes(bytes: Uint8Array): PrivateKey {
|
||||||
|
// draft-irtf-cfrg-bls-signature-04 does not allow SK == 0
|
||||||
|
if (isZeroUint8Array(bytes)) {
|
||||||
|
throw new ZeroPrivateKeyError();
|
||||||
|
}
|
||||||
|
|
||||||
const sk = blst.SecretKey.fromBytes(bytes);
|
const sk = blst.SecretKey.fromBytes(bytes);
|
||||||
return new PrivateKey(sk);
|
return new PrivateKey(sk);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,5 +3,3 @@ export const SIGNATURE_LENGTH = 96;
|
||||||
export const FP_POINT_LENGTH = 48;
|
export const FP_POINT_LENGTH = 48;
|
||||||
export const PUBLIC_KEY_LENGTH = FP_POINT_LENGTH;
|
export const PUBLIC_KEY_LENGTH = FP_POINT_LENGTH;
|
||||||
export const G2_HASH_PADDING = 16;
|
export const G2_HASH_PADDING = 16;
|
||||||
export const EMPTY_PUBLIC_KEY = new Uint8Array(PUBLIC_KEY_LENGTH);
|
|
||||||
export const EMPTY_SIGNATURE = new Uint8Array(SIGNATURE_LENGTH);
|
|
||||||
|
|
|
@ -3,14 +3,6 @@ import randomBytes from "randombytes";
|
||||||
// Single import to ease changing this lib if necessary
|
// Single import to ease changing this lib if necessary
|
||||||
export {randomBytes};
|
export {randomBytes};
|
||||||
|
|
||||||
export function isEqualBytes(a: Buffer | Uint8Array, b: Buffer | Uint8Array): boolean {
|
|
||||||
return toBuffer(a).equals(toBuffer(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toBuffer(input: Uint8Array): Buffer {
|
|
||||||
return Buffer.from(input.buffer, input.byteOffset, input.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate bytes to prevent confusing WASM errors downstream if bytes is null
|
* Validate bytes to prevent confusing WASM errors downstream if bytes is null
|
||||||
*/
|
*/
|
||||||
|
@ -24,3 +16,7 @@ export function validateBytes(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isZeroUint8Array(bytes: Uint8Array): boolean {
|
||||||
|
return bytes.every((byte) => byte === 0);
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {PublicKeyType} from "bls-eth-wasm";
|
import {PublicKeyType} from "bls-eth-wasm";
|
||||||
import {getContext} from "./context";
|
import {getContext} from "./context";
|
||||||
import {EMPTY_PUBLIC_KEY, PUBLIC_KEY_LENGTH} from "../constants";
|
import {PUBLIC_KEY_LENGTH} from "../constants";
|
||||||
import {bytesToHex, hexToBytes, isEqualBytes} from "../helpers";
|
import {bytesToHex, hexToBytes, isZeroUint8Array} from "../helpers";
|
||||||
import {IPublicKey} from "../interface";
|
import {IPublicKey} from "../interface";
|
||||||
import {ZeroPublicKeyError} from "../errors";
|
import {ZeroPublicKeyError} from "../errors";
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ export class PublicKey implements IPublicKey {
|
||||||
|
|
||||||
const context = getContext();
|
const context = getContext();
|
||||||
const publicKey = new context.PublicKey();
|
const publicKey = new context.PublicKey();
|
||||||
if (!isEqualBytes(EMPTY_PUBLIC_KEY, bytes)) {
|
if (!isZeroUint8Array(bytes)) {
|
||||||
publicKey.deserialize(bytes);
|
publicKey.deserialize(bytes);
|
||||||
}
|
}
|
||||||
return new PublicKey(publicKey);
|
return new PublicKey(publicKey);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {SIGNATURE_LENGTH, EMPTY_SIGNATURE} from "../constants";
|
import {SIGNATURE_LENGTH} from "../constants";
|
||||||
import {SignatureType} from "bls-eth-wasm";
|
import {SignatureType} from "bls-eth-wasm";
|
||||||
import {getContext} from "./context";
|
import {getContext} from "./context";
|
||||||
import {PublicKey} from "./publicKey";
|
import {PublicKey} from "./publicKey";
|
||||||
import {bytesToHex, hexToBytes, isEqualBytes} from "../helpers";
|
import {bytesToHex, hexToBytes, isZeroUint8Array} from "../helpers";
|
||||||
import {ISignature} from "../interface";
|
import {ISignature} from "../interface";
|
||||||
|
|
||||||
export class Signature implements ISignature {
|
export class Signature implements ISignature {
|
||||||
|
@ -23,7 +23,7 @@ export class Signature implements ISignature {
|
||||||
|
|
||||||
const context = getContext();
|
const context = getContext();
|
||||||
const signature = new context.Signature();
|
const signature = new context.Signature();
|
||||||
if (!isEqualBytes(EMPTY_SIGNATURE, bytes)) {
|
if (!isZeroUint8Array(bytes)) {
|
||||||
signature.deserialize(bytes);
|
signature.deserialize(bytes);
|
||||||
}
|
}
|
||||||
return new Signature(signature);
|
return new Signature(signature);
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import {expect} from "chai";
|
||||||
|
import {isZeroUint8Array} from "../../../src/helpers/utils";
|
||||||
|
|
||||||
|
describe("helpers / bytes", () => {
|
||||||
|
describe("isZeroUint8Array", () => {
|
||||||
|
const testCases: {isZero: boolean; hex: string}[] = [
|
||||||
|
{hex: "0x00", isZero: true},
|
||||||
|
{hex: "0x" + "00".repeat(32), isZero: true},
|
||||||
|
{hex: "0x" + "00".repeat(96), isZero: true},
|
||||||
|
{hex: "0x" + "00".repeat(31) + "01", isZero: false},
|
||||||
|
{
|
||||||
|
hex: "0xb6f21199594b56d77670564bf422cb331d5281ca2c1f9a45588a56881d8287ef8619efa6456d6cd2ef61306aa5b21311",
|
||||||
|
isZero: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const {hex, isZero} of testCases) {
|
||||||
|
it(`${hex} isZero = ${isZero}`, () => {
|
||||||
|
const bytes = hexToBytesNode(hex);
|
||||||
|
console.log(bytes);
|
||||||
|
expect(isZeroUint8Array(bytes)).to.equal(isZero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function hexToBytesNode(hex: string): Buffer {
|
||||||
|
return Buffer.from(hex.replace("0x", ""), "hex");
|
||||||
|
}
|
Reference in New Issue