mirror of https://github.com/waku-org/js-waku.git
Merge #753
753: Clean up crypto/secp256k1 dupe code r=D4nte a=D4nte Co-authored-by: Franck Royer <franck@status.im>
This commit is contained in:
commit
2011c76b30
|
@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Changed
|
||||
|
||||
- `waitForRemotePeer` waits for a Relay peer by default instead of Relay and Store.
|
||||
- **Breaking**: Removed dupe secp256k1 code, removed some unused APIs.
|
||||
|
||||
## [0.23.0] - 2022-05-19
|
||||
|
||||
|
|
12
src/index.ts
12
src/index.ts
|
@ -1,3 +1,9 @@
|
|||
export {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "./lib/crypto";
|
||||
|
||||
export { getPredefinedBootstrapNodes } from "./lib/discovery";
|
||||
export * as discovery from "./lib/discovery";
|
||||
|
||||
|
@ -11,12 +17,6 @@ export { Waku, DefaultPubSubTopic, Protocols } from "./lib/waku";
|
|||
export * as waku_message from "./lib/waku_message";
|
||||
export { WakuMessage } from "./lib/waku_message";
|
||||
|
||||
export {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "./lib/waku_message/version_1";
|
||||
|
||||
export * as waku_light_push from "./lib/waku_light_push";
|
||||
export {
|
||||
WakuLightPush,
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import nodeCrypto from "crypto";
|
||||
|
||||
import * as secp from "@noble/secp256k1";
|
||||
import * as sha3 from "js-sha3";
|
||||
import { concat } from "uint8arrays/concat";
|
||||
|
||||
import * as symmetric from "./waku_message/symmetric";
|
||||
import { PrivateKeySize } from "./waku_message/version_1";
|
||||
|
||||
declare const self: Record<string, any> | undefined;
|
||||
const crypto: { node?: any; web?: any } = {
|
||||
|
@ -22,3 +27,72 @@ export function getSubtle(): SubtleCrypto {
|
|||
|
||||
export const randomBytes = secp.utils.randomBytes;
|
||||
export const sha256 = secp.utils.sha256;
|
||||
|
||||
/**
|
||||
* Generate a new private key to be used for asymmetric encryption.
|
||||
*
|
||||
* Use {@link getPublicKey} to get the corresponding Public Key.
|
||||
*/
|
||||
export function generatePrivateKey(): Uint8Array {
|
||||
return randomBytes(PrivateKeySize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new symmetric key to be used for symmetric encryption.
|
||||
*/
|
||||
export function generateSymmetricKey(): Uint8Array {
|
||||
return randomBytes(symmetric.KeySize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the public key for the given private key, to be used for asymmetric
|
||||
* encryption.
|
||||
*/
|
||||
export const getPublicKey = secp.getPublicKey;
|
||||
|
||||
/**
|
||||
* ECDSA Sign a message with the given private key.
|
||||
*
|
||||
* @param message The message to sign, usually a hash.
|
||||
* @param privateKey The ECDSA private key to use to sign the message.
|
||||
*
|
||||
* @returns The signature and the recovery id concatenated.
|
||||
*/
|
||||
export async function sign(
|
||||
message: Uint8Array,
|
||||
privateKey: Uint8Array
|
||||
): Promise<Uint8Array> {
|
||||
const [signature, recoveryId] = await secp.sign(message, privateKey, {
|
||||
recovered: true,
|
||||
der: false,
|
||||
});
|
||||
return concat([signature, [recoveryId]], signature.length + 1);
|
||||
}
|
||||
|
||||
export function keccak256(input: Uint8Array): Uint8Array {
|
||||
return new Uint8Array(sha3.keccak256.arrayBuffer(input));
|
||||
}
|
||||
|
||||
export function compressPublicKey(publicKey: Uint8Array): Uint8Array {
|
||||
if (publicKey.length === 64) {
|
||||
publicKey = concat([[4], publicKey], 65);
|
||||
}
|
||||
const point = secp.Point.fromHex(publicKey);
|
||||
return point.toRawBytes(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify an ECDSA signature.
|
||||
*/
|
||||
export function verifySignature(
|
||||
signature: Uint8Array,
|
||||
message: Uint8Array | string,
|
||||
publicKey: Uint8Array
|
||||
): boolean {
|
||||
try {
|
||||
const _signature = secp.Signature.fromCompact(signature.slice(0, 64));
|
||||
return secp.verify(_signature, message, publicKey);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import * as secp from "@noble/secp256k1";
|
||||
import * as base32 from "hi-base32";
|
||||
import { fromString } from "uint8arrays/from-string";
|
||||
|
||||
import { keccak256, verifySignature } from "../crypto";
|
||||
import { ENR } from "../enr";
|
||||
import { keccak256Buf, utf8ToBytes } from "../utils";
|
||||
import { utf8ToBytes } from "../utils";
|
||||
|
||||
export type ENRRootValues = {
|
||||
eRoot: string;
|
||||
|
@ -46,17 +46,11 @@ export class ENRTree {
|
|||
64
|
||||
);
|
||||
|
||||
let isVerified;
|
||||
try {
|
||||
const _sig = secp.Signature.fromCompact(signatureBuffer.slice(0, 64));
|
||||
isVerified = secp.verify(
|
||||
_sig,
|
||||
keccak256Buf(signedComponentBuffer),
|
||||
new Uint8Array(decodedPublicKey)
|
||||
);
|
||||
} catch {
|
||||
isVerified = false;
|
||||
}
|
||||
const isVerified = verifySignature(
|
||||
signatureBuffer,
|
||||
keccak256(signedComponentBuffer),
|
||||
new Uint8Array(decodedPublicKey)
|
||||
);
|
||||
|
||||
if (!isVerified) throw new Error("Unable to verify ENRTree root signature");
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
import { bytesToHex } from "../utils";
|
||||
|
||||
import { NodeId } from "./types";
|
||||
|
||||
export function createNodeId(bytes: Uint8Array): NodeId {
|
||||
if (bytes.length !== 32) {
|
||||
throw new Error("NodeId must be 32 bytes in length");
|
||||
}
|
||||
return bytesToHex(bytes);
|
||||
}
|
|
@ -2,6 +2,7 @@ import { assert, expect } from "chai";
|
|||
import { Multiaddr } from "multiaddr";
|
||||
import PeerId from "peer-id";
|
||||
|
||||
import { getPublicKey } from "../crypto";
|
||||
import { bytesToHex, hexToBytes, utf8ToBytes } from "../utils";
|
||||
|
||||
import { ERR_INVALID_ID } from "./constants";
|
||||
|
@ -9,8 +10,6 @@ import { ENR } from "./enr";
|
|||
import { createKeypairFromPeerId, IKeypair } from "./keypair";
|
||||
import { Waku2 } from "./waku2_codec";
|
||||
|
||||
import { v4 } from "./index";
|
||||
|
||||
describe("ENR", function () {
|
||||
describe("Txt codec", () => {
|
||||
it("should encodeTxt and decodeTxt", async () => {
|
||||
|
@ -199,7 +198,7 @@ describe("ENR", function () {
|
|||
privateKey = hexToBytes(
|
||||
"b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
|
||||
);
|
||||
record = await ENR.createV4(v4.publicKey(privateKey));
|
||||
record = await ENR.createV4(getPublicKey(privateKey));
|
||||
record.setLocationMultiaddr(new Multiaddr("/ip4/127.0.0.1/udp/30303"));
|
||||
record.seq = seq;
|
||||
await record.encodeTxt(privateKey);
|
||||
|
@ -240,7 +239,7 @@ describe("ENR", function () {
|
|||
privateKey = hexToBytes(
|
||||
"b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
|
||||
);
|
||||
record = await ENR.createV4(v4.publicKey(privateKey));
|
||||
record = await ENR.createV4(getPublicKey(privateKey));
|
||||
});
|
||||
|
||||
it("should get / set UDP multiaddr", () => {
|
||||
|
|
|
@ -9,6 +9,7 @@ import { fromString } from "uint8arrays/from-string";
|
|||
import { toString } from "uint8arrays/to-string";
|
||||
import { encode as varintEncode } from "varint";
|
||||
|
||||
import { compressPublicKey, keccak256, verifySignature } from "../crypto";
|
||||
import { bytesToHex, bytesToUtf8, hexToBytes, utf8ToBytes } from "../utils";
|
||||
|
||||
import { ERR_INVALID_ID, ERR_NO_SIGNATURE, MAX_RECORD_SIZE } from "./constants";
|
||||
|
@ -22,7 +23,6 @@ import {
|
|||
import { decodeMultiaddrs, encodeMultiaddrs } from "./multiaddrs_codec";
|
||||
import { ENRKey, ENRValue, NodeId, SequenceNumber } from "./types";
|
||||
import * as v4 from "./v4";
|
||||
import { compressPublicKey } from "./v4";
|
||||
import { decodeWaku2, encodeWaku2, Waku2 } from "./waku2_codec";
|
||||
|
||||
const dbg = debug("waku:enr");
|
||||
|
@ -472,7 +472,7 @@ export class ENR extends Map<ENRKey, ENRValue> {
|
|||
if (!this.publicKey) {
|
||||
throw new Error("Failed to verify ENR: No public key");
|
||||
}
|
||||
return v4.verify(this.publicKey, data, signature);
|
||||
return verifySignature(signature, keccak256(data), this.publicKey);
|
||||
}
|
||||
|
||||
async sign(data: Uint8Array, privateKey: Uint8Array): Promise<Uint8Array> {
|
||||
|
|
|
@ -3,6 +3,5 @@ export const v4 = v4Crypto;
|
|||
export * from "./constants";
|
||||
export * from "./enr";
|
||||
export * from "./types";
|
||||
export * from "./create";
|
||||
export * from "./keypair";
|
||||
export * from "./waku2_codec";
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
export const ERR_TYPE_NOT_IMPLEMENTED = "Keypair type not implemented";
|
||||
export const ERR_INVALID_KEYPAIR_TYPE = "Invalid keypair type";
|
|
@ -2,12 +2,7 @@ import { expect } from "chai";
|
|||
import { keys } from "libp2p-crypto";
|
||||
import PeerId from "peer-id";
|
||||
|
||||
import {
|
||||
AbstractKeypair,
|
||||
createPeerIdFromKeypair,
|
||||
generateKeypair,
|
||||
KeypairType,
|
||||
} from "./index";
|
||||
import { createPeerIdFromKeypair, generateKeypair, KeypairType } from "./index";
|
||||
|
||||
const { supportedKeys } = keys;
|
||||
|
||||
|
@ -27,7 +22,7 @@ describe("createPeerIdFromKeypair", function () {
|
|||
|
||||
it("should properly create a PeerId from a secp256k1 keypair without private key", async function () {
|
||||
const keypair = await generateKeypair(KeypairType.secp256k1);
|
||||
delete (keypair as AbstractKeypair)._privateKey;
|
||||
delete (keypair as any)._privateKey;
|
||||
const pubKey = new supportedKeys.secp256k1.Secp256k1PublicKey(
|
||||
keypair.publicKey
|
||||
);
|
||||
|
|
|
@ -2,12 +2,12 @@ import { keys } from "libp2p-crypto";
|
|||
import { identity } from "multiformats/hashes/identity";
|
||||
import PeerId from "peer-id";
|
||||
|
||||
const { keysPBM, supportedKeys } = keys;
|
||||
|
||||
import { ERR_TYPE_NOT_IMPLEMENTED } from "./constants";
|
||||
import { Secp256k1Keypair } from "./secp256k1";
|
||||
import { IKeypair, KeypairType } from "./types";
|
||||
|
||||
const { keysPBM, supportedKeys } = keys;
|
||||
|
||||
export const ERR_TYPE_NOT_IMPLEMENTED = "Keypair type not implemented";
|
||||
export * from "./types";
|
||||
export * from "./secp256k1";
|
||||
|
||||
|
|
|
@ -1,46 +1,26 @@
|
|||
import * as secp from "@noble/secp256k1";
|
||||
import { concat } from "uint8arrays/concat";
|
||||
|
||||
import { randomBytes } from "../../crypto";
|
||||
import { compressPublicKey, randomBytes } from "../../crypto";
|
||||
|
||||
import { AbstractKeypair, IKeypair, IKeypairClass, KeypairType } from "./types";
|
||||
import { IKeypair, KeypairType } from "./types";
|
||||
|
||||
export function secp256k1PublicKeyToCompressed(
|
||||
publicKey: Uint8Array
|
||||
): Uint8Array {
|
||||
if (publicKey.length === 64) {
|
||||
publicKey = concat([[4], publicKey], 65);
|
||||
}
|
||||
const point = secp.Point.fromHex(publicKey);
|
||||
return point.toRawBytes(true);
|
||||
}
|
||||
|
||||
export function secp256k1PublicKeyToFull(publicKey: Uint8Array): Uint8Array {
|
||||
if (publicKey.length === 64) {
|
||||
publicKey = concat([[4], publicKey], 65);
|
||||
}
|
||||
const point = secp.Point.fromHex(publicKey);
|
||||
|
||||
return point.toRawBytes(false);
|
||||
}
|
||||
|
||||
export function secp256k1PublicKeyToRaw(publicKey: Uint8Array): Uint8Array {
|
||||
const point = secp.Point.fromHex(publicKey);
|
||||
return point.toRawBytes(false).slice(1);
|
||||
}
|
||||
|
||||
export const Secp256k1Keypair: IKeypairClass = class Secp256k1Keypair
|
||||
extends AbstractKeypair
|
||||
implements IKeypair
|
||||
{
|
||||
export class Secp256k1Keypair implements IKeypair {
|
||||
readonly type: KeypairType;
|
||||
_privateKey?: Uint8Array;
|
||||
readonly _publicKey?: Uint8Array;
|
||||
|
||||
constructor(privateKey?: Uint8Array, publicKey?: Uint8Array) {
|
||||
let pub = publicKey;
|
||||
if (pub) {
|
||||
pub = secp256k1PublicKeyToCompressed(pub);
|
||||
pub = compressPublicKey(pub);
|
||||
}
|
||||
super(privateKey, pub);
|
||||
if ((this._privateKey = privateKey) && !this.privateKeyVerify()) {
|
||||
throw new Error("Invalid private key");
|
||||
}
|
||||
if ((this._publicKey = pub) && !this.publicKeyVerify()) {
|
||||
throw new Error("Invalid public key");
|
||||
}
|
||||
|
||||
this.type = KeypairType.secp256k1;
|
||||
}
|
||||
|
||||
|
@ -69,20 +49,21 @@ export const Secp256k1Keypair: IKeypairClass = class Secp256k1Keypair
|
|||
return true;
|
||||
}
|
||||
|
||||
async sign(msg: Uint8Array): Promise<Uint8Array> {
|
||||
const [signature, recid] = await secp.sign(msg, this.privateKey, {
|
||||
recovered: true,
|
||||
der: false,
|
||||
});
|
||||
return concat([signature, [recid]], signature.length + 1);
|
||||
get privateKey(): Uint8Array {
|
||||
if (!this._privateKey) {
|
||||
throw new Error();
|
||||
}
|
||||
return this._privateKey;
|
||||
}
|
||||
|
||||
verify(msg: Uint8Array, sig: Uint8Array): boolean {
|
||||
try {
|
||||
const _sig = secp.Signature.fromCompact(sig.slice(0, 64));
|
||||
return secp.verify(_sig, msg, this.publicKey);
|
||||
} catch {
|
||||
return false;
|
||||
get publicKey(): Uint8Array {
|
||||
if (!this._publicKey) {
|
||||
throw new Error();
|
||||
}
|
||||
return this._publicKey;
|
||||
}
|
||||
};
|
||||
|
||||
hasPrivateKey(): boolean {
|
||||
return !!this._privateKey;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,52 +10,5 @@ export interface IKeypair {
|
|||
publicKey: Uint8Array;
|
||||
privateKeyVerify(): boolean;
|
||||
publicKeyVerify(): boolean;
|
||||
sign(msg: Uint8Array): Promise<Uint8Array>;
|
||||
verify(msg: Uint8Array, sig: Uint8Array): boolean;
|
||||
hasPrivateKey(): boolean;
|
||||
}
|
||||
|
||||
export interface IKeypairClass {
|
||||
new (privateKey?: Uint8Array, publicKey?: Uint8Array): IKeypair;
|
||||
generate(): Promise<IKeypair>;
|
||||
}
|
||||
|
||||
export abstract class AbstractKeypair {
|
||||
_privateKey?: Uint8Array;
|
||||
readonly _publicKey?: Uint8Array;
|
||||
|
||||
constructor(privateKey?: Uint8Array, publicKey?: Uint8Array) {
|
||||
if ((this._privateKey = privateKey) && !this.privateKeyVerify()) {
|
||||
throw new Error("Invalid private key");
|
||||
}
|
||||
if ((this._publicKey = publicKey) && !this.publicKeyVerify()) {
|
||||
throw new Error("Invalid public key");
|
||||
}
|
||||
}
|
||||
|
||||
get privateKey(): Uint8Array {
|
||||
if (!this._privateKey) {
|
||||
throw new Error();
|
||||
}
|
||||
return this._privateKey;
|
||||
}
|
||||
|
||||
get publicKey(): Uint8Array {
|
||||
if (!this._publicKey) {
|
||||
throw new Error();
|
||||
}
|
||||
return this._publicKey;
|
||||
}
|
||||
|
||||
privateKeyVerify(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
publicKeyVerify(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
hasPrivateKey(): boolean {
|
||||
return Boolean(this._privateKey);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,83 +1,22 @@
|
|||
import * as secp from "@noble/secp256k1";
|
||||
import { keccak256 } from "js-sha3";
|
||||
|
||||
import { randomBytes } from "../crypto";
|
||||
import { keccak256 } from "../crypto";
|
||||
import { bytesToHex } from "../utils";
|
||||
|
||||
import { createNodeId } from "./create";
|
||||
import { NodeId } from "./types";
|
||||
|
||||
export function hash(input: Uint8Array): Uint8Array {
|
||||
return new Uint8Array(keccak256.arrayBuffer(input));
|
||||
}
|
||||
|
||||
export function createPrivateKey(): Uint8Array {
|
||||
return randomBytes(32);
|
||||
}
|
||||
|
||||
export function publicKey(privKey: Uint8Array): Uint8Array {
|
||||
return secp.getPublicKey(privKey, true);
|
||||
}
|
||||
|
||||
export function compressPublicKey(publicKey: Uint8Array): Uint8Array {
|
||||
const point = secp.Point.fromHex(bytesToHex(publicKey));
|
||||
return point.toRawBytes(true);
|
||||
}
|
||||
|
||||
export async function sign(
|
||||
privKey: Uint8Array,
|
||||
msg: Uint8Array
|
||||
): Promise<Uint8Array> {
|
||||
return secp.sign(hash(msg), privKey, {
|
||||
return secp.sign(keccak256(msg), privKey, {
|
||||
der: false,
|
||||
});
|
||||
}
|
||||
|
||||
export function verify(
|
||||
pubKey: Uint8Array,
|
||||
msg: Uint8Array,
|
||||
sig: Uint8Array
|
||||
): boolean {
|
||||
try {
|
||||
const _sig = secp.Signature.fromCompact(sig.slice(0, 64));
|
||||
return secp.verify(_sig, hash(msg), pubKey);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function nodeId(pubKey: Uint8Array): NodeId {
|
||||
const publicKey = secp.Point.fromHex(pubKey);
|
||||
const uncompressedPubkey = publicKey.toRawBytes(false);
|
||||
|
||||
return createNodeId(hash(uncompressedPubkey.slice(1)));
|
||||
}
|
||||
|
||||
export class ENRKeyPair {
|
||||
public constructor(
|
||||
public readonly nodeId: NodeId,
|
||||
public readonly privateKey: Uint8Array,
|
||||
public readonly publicKey: Uint8Array
|
||||
) {}
|
||||
|
||||
public static create(privateKey?: Uint8Array): ENRKeyPair {
|
||||
if (privateKey) {
|
||||
if (!secp.utils.isValidPrivateKey(privateKey)) {
|
||||
throw new Error("Invalid private key");
|
||||
}
|
||||
}
|
||||
const _privateKey = privateKey || createPrivateKey();
|
||||
const _publicKey = publicKey(_privateKey);
|
||||
const _nodeId = nodeId(_publicKey);
|
||||
|
||||
return new ENRKeyPair(_nodeId, _privateKey, _publicKey);
|
||||
}
|
||||
|
||||
public async sign(msg: Uint8Array): Promise<Uint8Array> {
|
||||
return sign(this.privateKey, msg);
|
||||
}
|
||||
|
||||
public verify(msg: Uint8Array, sig: Uint8Array): boolean {
|
||||
return verify(this.publicKey, msg, sig);
|
||||
}
|
||||
return bytesToHex(keccak256(uncompressedPubkey.slice(1)));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { keccak256, Message } from "js-sha3";
|
||||
import { fromString } from "uint8arrays/from-string";
|
||||
import { toString } from "uint8arrays/to-string";
|
||||
|
||||
|
@ -21,13 +20,6 @@ export function hexToBytes(hex: string | Uint8Array): Uint8Array {
|
|||
export const bytesToHex = (bytes: Uint8Array): string =>
|
||||
toString(bytes, "base16");
|
||||
|
||||
/**
|
||||
* Return Keccak-256 of the input.
|
||||
*/
|
||||
export function keccak256Buf(message: Message): Uint8Array {
|
||||
return new Uint8Array(keccak256.arrayBuffer(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode byte array to utf-8 string.
|
||||
*/
|
||||
|
|
|
@ -9,9 +9,9 @@ import {
|
|||
} from "../test_utils/";
|
||||
import { delay } from "../test_utils/delay";
|
||||
|
||||
import { generateSymmetricKey } from "./crypto";
|
||||
import { Protocols, Waku } from "./waku";
|
||||
import { WakuMessage } from "./waku_message";
|
||||
import { generateSymmetricKey } from "./waku_message/version_1";
|
||||
|
||||
const TestContentTopic = "/test/1/waku/utf8";
|
||||
|
||||
|
|
|
@ -8,14 +8,13 @@ import {
|
|||
WakuRelayMessage,
|
||||
} from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { bytesToHex, bytesToUtf8, hexToBytes, utf8ToBytes } from "../utils";
|
||||
import { Protocols, Waku } from "../waku";
|
||||
|
||||
import {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "./version_1";
|
||||
} from "../crypto";
|
||||
import { bytesToHex, bytesToUtf8, hexToBytes, utf8ToBytes } from "../utils";
|
||||
import { Protocols, Waku } from "../waku";
|
||||
|
||||
import { DecryptionMethod, WakuMessage } from "./index";
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { expect } from "chai";
|
||||
import fc from "fast-check";
|
||||
|
||||
import { getPublicKey } from "./version_1";
|
||||
import { getPublicKey } from "../crypto";
|
||||
|
||||
import { WakuMessage } from "./index";
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { expect } from "chai";
|
||||
import fc from "fast-check";
|
||||
|
||||
import { getPublicKey } from "../crypto";
|
||||
|
||||
import {
|
||||
clearDecode,
|
||||
clearEncode,
|
||||
|
@ -8,7 +10,6 @@ import {
|
|||
decryptSymmetric,
|
||||
encryptAsymmetric,
|
||||
encryptSymmetric,
|
||||
getPublicKey,
|
||||
} from "./version_1";
|
||||
|
||||
describe("Waku Message Version 1", function () {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import * as secp from "@noble/secp256k1";
|
||||
import { keccak256 } from "js-sha3";
|
||||
import { concat } from "uint8arrays/concat";
|
||||
|
||||
import { randomBytes } from "../crypto";
|
||||
import { keccak256, randomBytes, sign } from "../crypto";
|
||||
import { hexToBytes } from "../utils";
|
||||
|
||||
import * as ecies from "./ecies";
|
||||
|
@ -62,15 +61,11 @@ export async function clearEncode(
|
|||
if (sigPrivKey) {
|
||||
envelope[0] |= IsSignedMask;
|
||||
const hash = keccak256(envelope);
|
||||
const [hexSignature, recid] = await secp.sign(hash, sigPrivKey, {
|
||||
recovered: true,
|
||||
der: false,
|
||||
});
|
||||
const bytesSignature = hexToBytes(hexSignature);
|
||||
envelope = concat([envelope, bytesSignature, [recid]]);
|
||||
const bytesSignature = await sign(hash, sigPrivKey);
|
||||
envelope = concat([envelope, bytesSignature]);
|
||||
sig = {
|
||||
signature: bytesSignature,
|
||||
publicKey: getPublicKey(sigPrivKey),
|
||||
publicKey: secp.getPublicKey(sigPrivKey, false),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -199,30 +194,6 @@ export async function decryptSymmetric(
|
|||
return symmetric.decrypt(iv, hexToBytes(key), cipher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new private key to be used for asymmetric encryption.
|
||||
*
|
||||
* Use {@link getPublicKey} to get the corresponding Public Key.
|
||||
*/
|
||||
export function generatePrivateKey(): Uint8Array {
|
||||
return randomBytes(PrivateKeySize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new symmetric key to be used for symmetric encryption.
|
||||
*/
|
||||
export function generateSymmetricKey(): Uint8Array {
|
||||
return randomBytes(symmetric.KeySize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the public key for the given private key, to be used for asymmetric
|
||||
* encryption.
|
||||
*/
|
||||
export function getPublicKey(privateKey: Uint8Array): Uint8Array {
|
||||
return secp.getPublicKey(privateKey, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the flags & auxiliary-field as per [26/WAKU-PAYLOAD](https://rfc.vac.dev/spec/26/).
|
||||
*/
|
||||
|
@ -263,7 +234,7 @@ function getSignature(message: Uint8Array): Uint8Array {
|
|||
return message.slice(message.length - SignatureLength, message.length);
|
||||
}
|
||||
|
||||
function getHash(message: Uint8Array, isSigned: boolean): string {
|
||||
function getHash(message: Uint8Array, isSigned: boolean): Uint8Array {
|
||||
if (isSigned) {
|
||||
return keccak256(message.slice(0, message.length - SignatureLength));
|
||||
}
|
||||
|
@ -271,7 +242,7 @@ function getHash(message: Uint8Array, isSigned: boolean): string {
|
|||
}
|
||||
|
||||
function ecRecoverPubKey(
|
||||
messageHash: string,
|
||||
messageHash: Uint8Array,
|
||||
signature: Uint8Array
|
||||
): Uint8Array | undefined {
|
||||
const recoveryDataView = new DataView(signature.slice(64).buffer);
|
||||
|
@ -279,7 +250,7 @@ function ecRecoverPubKey(
|
|||
const _signature = secp.Signature.fromCompact(signature.slice(0, 64));
|
||||
|
||||
return secp.recoverPublicKey(
|
||||
hexToBytes(messageHash),
|
||||
messageHash,
|
||||
_signature,
|
||||
recovery,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
|
|
|
@ -8,13 +8,13 @@ import {
|
|||
Nwaku,
|
||||
} from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { DefaultPubSubTopic, Protocols, Waku } from "../waku";
|
||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||
import {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "../waku_message/version_1";
|
||||
} from "../crypto";
|
||||
import { DefaultPubSubTopic, Protocols, Waku } from "../waku";
|
||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||
|
||||
const log = debug("waku:test");
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@ import {
|
|||
Nwaku,
|
||||
} from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { Protocols, Waku } from "../waku";
|
||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||
import {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "../waku_message/version_1";
|
||||
} from "../crypto";
|
||||
import { Protocols, Waku } from "../waku";
|
||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||
|
||||
import { PageDirection } from "./history_rpc";
|
||||
|
||||
|
|
Loading…
Reference in New Issue