mirror of https://github.com/waku-org/js-waku.git
feat!: export crypto primitives (#1728)
* export crypto primitives * export crypto * update imports * fix size limit * rename crypto.js * move Signature type * fix path * fix: size-limit (#1734) * fix paths, revert change to config --------- Co-authored-by: Danish Arora <35004822+danisharora099@users.noreply.github.com>
This commit is contained in:
parent
7df21b7756
commit
7eb3375f50
|
@ -16,6 +16,10 @@
|
|||
"./symmetric": {
|
||||
"types": "./dist/symmetric.d.ts",
|
||||
"import": "./dist/symmetric.js"
|
||||
},
|
||||
"./crypto": {
|
||||
"types": "./dist/crypto/index.d.ts",
|
||||
"import": "./dist/crypto/index.js"
|
||||
}
|
||||
},
|
||||
"typesVersions": {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as secp from "@noble/secp256k1";
|
||||
import { concat, hexToBytes } from "@waku/utils/bytes";
|
||||
|
||||
import { getSubtle, randomBytes, sha256 } from "./index.js";
|
||||
import { getSubtle, randomBytes, sha256 } from "./utils.js";
|
||||
/**
|
||||
* HKDF as implemented in go-ethereum.
|
||||
*/
|
||||
|
|
|
@ -1,76 +1,3 @@
|
|||
import nodeCrypto from "crypto";
|
||||
|
||||
import * as secp from "@noble/secp256k1";
|
||||
import { concat } from "@waku/utils/bytes";
|
||||
import sha3 from "js-sha3";
|
||||
|
||||
import { Asymmetric, Symmetric } from "../constants.js";
|
||||
|
||||
declare const self: Record<string, any> | undefined;
|
||||
const crypto: { node?: any; web?: any } = {
|
||||
node: nodeCrypto,
|
||||
web: typeof self === "object" && "crypto" in self ? self.crypto : undefined
|
||||
};
|
||||
|
||||
export function getSubtle(): SubtleCrypto {
|
||||
if (crypto.web) {
|
||||
return crypto.web.subtle;
|
||||
} else if (crypto.node) {
|
||||
return crypto.node.webcrypto.subtle;
|
||||
} else {
|
||||
throw new Error(
|
||||
"The environment doesn't have Crypto Subtle API (if in the browser, be sure to use to be in a secure context, ie, https)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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(Asymmetric.keySize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, new Uint8Array([recoveryId])],
|
||||
signature.length + 1
|
||||
);
|
||||
}
|
||||
|
||||
export function keccak256(input: Uint8Array): Uint8Array {
|
||||
return new Uint8Array(sha3.keccak256.arrayBuffer(input));
|
||||
}
|
||||
export * from "./utils.js";
|
||||
export * as ecies from "./ecies.js";
|
||||
export * as symmetric from "./symmetric.js";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Symmetric } from "../constants.js";
|
||||
import { Symmetric } from "../misc.js";
|
||||
|
||||
import { getSubtle, randomBytes } from "./index.js";
|
||||
import { getSubtle, randomBytes } from "./utils.js";
|
||||
|
||||
export async function encrypt(
|
||||
iv: Uint8Array,
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import nodeCrypto from "crypto";
|
||||
|
||||
import * as secp from "@noble/secp256k1";
|
||||
import { concat } from "@waku/utils/bytes";
|
||||
import sha3 from "js-sha3";
|
||||
|
||||
import { Asymmetric, Symmetric } from "../misc.js";
|
||||
|
||||
declare const self: Record<string, any> | undefined;
|
||||
const crypto: { node?: any; web?: any } = {
|
||||
node: nodeCrypto,
|
||||
web: typeof self === "object" && "crypto" in self ? self.crypto : undefined
|
||||
};
|
||||
|
||||
export function getSubtle(): SubtleCrypto {
|
||||
if (crypto.web) {
|
||||
return crypto.web.subtle;
|
||||
} else if (crypto.node) {
|
||||
return crypto.node.webcrypto.subtle;
|
||||
} else {
|
||||
throw new Error(
|
||||
"The environment doesn't have Crypto Subtle API (if in the browser, be sure to use to be in a secure context, ie, https)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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(Asymmetric.keySize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, new Uint8Array([recoveryId])],
|
||||
signature.length + 1
|
||||
);
|
||||
}
|
||||
|
||||
export function keccak256(input: Uint8Array): Uint8Array {
|
||||
return new Uint8Array(sha3.keccak256.arrayBuffer(input));
|
||||
}
|
|
@ -1,33 +1,34 @@
|
|||
import { DefaultPubsubTopic } from "@waku/core";
|
||||
import { Decoder as DecoderV0 } from "@waku/core/lib/message/version_0";
|
||||
import { IMetaSetter, PubsubTopic } from "@waku/interfaces";
|
||||
import type {
|
||||
EncoderOptions as BaseEncoderOptions,
|
||||
IDecoder,
|
||||
IEncoder,
|
||||
IMessage,
|
||||
IProtoMessage
|
||||
IMetaSetter,
|
||||
IProtoMessage,
|
||||
PubsubTopic
|
||||
} from "@waku/interfaces";
|
||||
import { WakuMessage } from "@waku/proto";
|
||||
import { Logger } from "@waku/utils";
|
||||
|
||||
import { generatePrivateKey } from "./crypto/utils.js";
|
||||
import { DecodedMessage } from "./decoded_message.js";
|
||||
import {
|
||||
decryptAsymmetric,
|
||||
encryptAsymmetric,
|
||||
postCipher,
|
||||
preCipher
|
||||
} from "./waku_payload.js";
|
||||
} from "./encryption.js";
|
||||
import { OneMillion, Version } from "./misc.js";
|
||||
|
||||
import {
|
||||
generatePrivateKey,
|
||||
getPublicKey,
|
||||
OneMillion,
|
||||
Version
|
||||
} from "./index.js";
|
||||
|
||||
export { generatePrivateKey, getPublicKey };
|
||||
export type { Encoder, Decoder, DecodedMessage };
|
||||
export {
|
||||
decryptAsymmetric,
|
||||
encryptAsymmetric,
|
||||
postCipher,
|
||||
preCipher,
|
||||
generatePrivateKey
|
||||
};
|
||||
|
||||
const log = new Logger("message-encryption:ecies");
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ import {
|
|||
encryptSymmetric,
|
||||
postCipher,
|
||||
preCipher
|
||||
} from "./waku_payload.js";
|
||||
} from "./encryption.js";
|
||||
|
||||
describe("Waku Payload", function () {
|
||||
describe("Waku Encryption", function () {
|
||||
this.timeout(20000);
|
||||
it("Asymmetric encrypt & decrypt", async function () {
|
||||
await fc.assert(
|
|
@ -1,12 +1,14 @@
|
|||
import * as secp from "@noble/secp256k1";
|
||||
import { concat, hexToBytes } from "@waku/utils/bytes";
|
||||
|
||||
import { Symmetric } from "./constants.js";
|
||||
import * as ecies from "./crypto/ecies.js";
|
||||
import { keccak256, randomBytes, sign } from "./crypto/index.js";
|
||||
import * as symmetric from "./crypto/symmetric.js";
|
||||
|
||||
import { Signature } from "./index.js";
|
||||
import {
|
||||
ecies,
|
||||
keccak256,
|
||||
randomBytes,
|
||||
sign,
|
||||
symmetric
|
||||
} from "./crypto/index.js";
|
||||
import { Symmetric } from "./misc.js";
|
||||
|
||||
const FlagsLength = 1;
|
||||
const FlagMask = 3; // 0011
|
||||
|
@ -210,6 +212,11 @@ export async function preCipher(
|
|||
return envelope;
|
||||
}
|
||||
|
||||
type Signature = {
|
||||
signature: Uint8Array;
|
||||
publicKey: Uint8Array | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode a decrypted payload.
|
||||
*
|
|
@ -5,17 +5,9 @@ import {
|
|||
} from "./crypto/index.js";
|
||||
import { DecodedMessage } from "./decoded_message.js";
|
||||
|
||||
export const OneMillion = BigInt(1_000_000);
|
||||
|
||||
export { generatePrivateKey, generateSymmetricKey, getPublicKey };
|
||||
export type { DecodedMessage };
|
||||
|
||||
export * as ecies from "./ecies.js";
|
||||
export * as symmetric from "./symmetric.js";
|
||||
|
||||
export const Version = 1;
|
||||
|
||||
export type Signature = {
|
||||
signature: Uint8Array;
|
||||
publicKey: Uint8Array | undefined;
|
||||
};
|
||||
export * as crypto from "./crypto";
|
||||
|
|
|
@ -8,3 +8,7 @@ export const Symmetric = {
|
|||
export const Asymmetric = {
|
||||
keySize: 32
|
||||
};
|
||||
|
||||
export const OneMillion = BigInt(1_000_000);
|
||||
|
||||
export const Version = 1;
|
|
@ -12,18 +12,23 @@ import type {
|
|||
import { WakuMessage } from "@waku/proto";
|
||||
import { Logger } from "@waku/utils";
|
||||
|
||||
import { generateSymmetricKey } from "./crypto/utils.js";
|
||||
import { DecodedMessage } from "./decoded_message.js";
|
||||
import {
|
||||
decryptSymmetric,
|
||||
encryptSymmetric,
|
||||
postCipher,
|
||||
preCipher
|
||||
} from "./waku_payload.js";
|
||||
} from "./encryption.js";
|
||||
import { OneMillion, Version } from "./misc.js";
|
||||
|
||||
import { generateSymmetricKey, OneMillion, Version } from "./index.js";
|
||||
|
||||
export { generateSymmetricKey };
|
||||
export type { DecodedMessage, Encoder, Decoder };
|
||||
export {
|
||||
decryptSymmetric,
|
||||
encryptSymmetric,
|
||||
postCipher,
|
||||
preCipher,
|
||||
generateSymmetricKey
|
||||
};
|
||||
|
||||
const log = new Logger("message-encryption:symmetric");
|
||||
|
||||
|
|
|
@ -7,13 +7,15 @@ import {
|
|||
import { IFilterSubscription, Protocols } from "@waku/interfaces";
|
||||
import type { LightNode } from "@waku/interfaces";
|
||||
import {
|
||||
createDecoder as eciesDecoder,
|
||||
createEncoder as eciesEncoder,
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey
|
||||
} from "@waku/message-encryption";
|
||||
import {
|
||||
createDecoder as eciesDecoder,
|
||||
createEncoder as eciesEncoder
|
||||
} from "@waku/message-encryption/ecies";
|
||||
import {
|
||||
generateSymmetricKey,
|
||||
createDecoder as symDecoder,
|
||||
createEncoder as symEncoder
|
||||
} from "@waku/message-encryption/symmetric";
|
||||
|
|
|
@ -6,7 +6,13 @@ import {
|
|||
} from "@waku/core";
|
||||
import type { IFilterSubscription, LightNode } from "@waku/interfaces";
|
||||
import { Protocols } from "@waku/interfaces";
|
||||
import { ecies, symmetric } from "@waku/message-encryption";
|
||||
import {
|
||||
ecies,
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
symmetric
|
||||
} from "@waku/message-encryption";
|
||||
import { utf8ToBytes } from "@waku/utils/bytes";
|
||||
import { expect } from "chai";
|
||||
|
||||
|
@ -67,8 +73,8 @@ describe("Waku Filter V2: Subscribe", function () {
|
|||
});
|
||||
|
||||
it("Subscribe and receive ecies encrypted messages via lightPush", async function () {
|
||||
const privateKey = ecies.generatePrivateKey();
|
||||
const publicKey = ecies.getPublicKey(privateKey);
|
||||
const privateKey = generatePrivateKey();
|
||||
const publicKey = getPublicKey(privateKey);
|
||||
const encoder = ecies.createEncoder({
|
||||
contentTopic: TestContentTopic,
|
||||
publicKey
|
||||
|
@ -89,7 +95,7 @@ describe("Waku Filter V2: Subscribe", function () {
|
|||
});
|
||||
|
||||
it("Subscribe and receive symmetrically encrypted messages via lightPush", async function () {
|
||||
const symKey = symmetric.generateSymmetricKey();
|
||||
const symKey = generateSymmetricKey();
|
||||
const encoder = symmetric.createEncoder({
|
||||
contentTopic: TestContentTopic,
|
||||
symKey
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import { createDecoder, createEncoder, DecodedMessage } from "@waku/core";
|
||||
import { RelayNode } from "@waku/interfaces";
|
||||
import {
|
||||
createDecoder as createEciesDecoder,
|
||||
createEncoder as createEciesEncoder,
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey
|
||||
} from "@waku/message-encryption";
|
||||
import {
|
||||
createDecoder as createEciesDecoder,
|
||||
createEncoder as createEciesEncoder
|
||||
} from "@waku/message-encryption/ecies";
|
||||
import {
|
||||
createDecoder as createSymDecoder,
|
||||
createEncoder as createSymEncoder,
|
||||
generateSymmetricKey
|
||||
createEncoder as createSymEncoder
|
||||
} from "@waku/message-encryption/symmetric";
|
||||
import { createRelayNode } from "@waku/sdk";
|
||||
import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes";
|
||||
|
|
|
@ -7,15 +7,17 @@ import {
|
|||
import type { IMessage, LightNode } from "@waku/interfaces";
|
||||
import { Protocols } from "@waku/interfaces";
|
||||
import {
|
||||
createDecoder as createEciesDecoder,
|
||||
createEncoder as createEciesEncoder,
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey
|
||||
} from "@waku/message-encryption";
|
||||
import {
|
||||
createDecoder as createEciesDecoder,
|
||||
createEncoder as createEciesEncoder
|
||||
} from "@waku/message-encryption/ecies";
|
||||
import {
|
||||
createDecoder as createSymDecoder,
|
||||
createEncoder as createSymEncoder,
|
||||
generateSymmetricKey
|
||||
createEncoder as createSymEncoder
|
||||
} from "@waku/message-encryption/symmetric";
|
||||
import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes";
|
||||
import { expect } from "chai";
|
||||
|
|
|
@ -7,10 +7,10 @@ import {
|
|||
} from "@waku/core";
|
||||
import type { LightNode, RelayNode, Waku } from "@waku/interfaces";
|
||||
import { Protocols } from "@waku/interfaces";
|
||||
import { generateSymmetricKey } from "@waku/message-encryption";
|
||||
import {
|
||||
createDecoder,
|
||||
createEncoder,
|
||||
generateSymmetricKey
|
||||
createEncoder
|
||||
} from "@waku/message-encryption/symmetric";
|
||||
import {
|
||||
createLightNode,
|
||||
|
|
Loading…
Reference in New Issue