diff --git a/packages/message-encryption/package.json b/packages/message-encryption/package.json index 1faca460f2..4dc5498ef3 100644 --- a/packages/message-encryption/package.json +++ b/packages/message-encryption/package.json @@ -16,10 +16,6 @@ "./symmetric": { "types": "./dist/symmetric.d.ts", "import": "./dist/symmetric.js" - }, - "./crypto": { - "types": "./dist/crypto/index.d.ts", - "import": "./dist/crypto/index.js" } }, "typesVersions": { diff --git a/packages/message-encryption/src/misc.ts b/packages/message-encryption/src/constants.ts similarity index 69% rename from packages/message-encryption/src/misc.ts rename to packages/message-encryption/src/constants.ts index 9491453b7a..586a792fe5 100644 --- a/packages/message-encryption/src/misc.ts +++ b/packages/message-encryption/src/constants.ts @@ -8,7 +8,3 @@ export const Symmetric = { export const Asymmetric = { keySize: 32 }; - -export const OneMillion = BigInt(1_000_000); - -export const Version = 1; diff --git a/packages/message-encryption/src/crypto/ecies.ts b/packages/message-encryption/src/crypto/ecies.ts index a53d3ef558..d8f16557b2 100644 --- a/packages/message-encryption/src/crypto/ecies.ts +++ b/packages/message-encryption/src/crypto/ecies.ts @@ -1,7 +1,7 @@ import * as secp from "@noble/secp256k1"; import { concat, hexToBytes } from "@waku/utils/bytes"; -import { getSubtle, randomBytes, sha256 } from "./utils.js"; +import { getSubtle, randomBytes, sha256 } from "./index.js"; /** * HKDF as implemented in go-ethereum. */ diff --git a/packages/message-encryption/src/crypto/index.ts b/packages/message-encryption/src/crypto/index.ts index 7c247f255f..78e23d7774 100644 --- a/packages/message-encryption/src/crypto/index.ts +++ b/packages/message-encryption/src/crypto/index.ts @@ -1,3 +1,76 @@ -export * from "./utils.js"; -export * as ecies from "./ecies.js"; -export * as symmetric from "./symmetric.js"; +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 | 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 { + 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)); +} diff --git a/packages/message-encryption/src/crypto/symmetric.ts b/packages/message-encryption/src/crypto/symmetric.ts index faaeb4acb0..35f69f4558 100644 --- a/packages/message-encryption/src/crypto/symmetric.ts +++ b/packages/message-encryption/src/crypto/symmetric.ts @@ -1,6 +1,6 @@ -import { Symmetric } from "../misc.js"; +import { Symmetric } from "../constants.js"; -import { getSubtle, randomBytes } from "./utils.js"; +import { getSubtle, randomBytes } from "./index.js"; export async function encrypt( iv: Uint8Array, diff --git a/packages/message-encryption/src/crypto/utils.ts b/packages/message-encryption/src/crypto/utils.ts deleted file mode 100644 index fd57811bd4..0000000000 --- a/packages/message-encryption/src/crypto/utils.ts +++ /dev/null @@ -1,76 +0,0 @@ -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 | 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 { - 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)); -} diff --git a/packages/message-encryption/src/ecies.ts b/packages/message-encryption/src/ecies.ts index 24d7aa0fee..7b6f35410f 100644 --- a/packages/message-encryption/src/ecies.ts +++ b/packages/message-encryption/src/ecies.ts @@ -1,35 +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, - IMetaSetter, IProtoMessage, - PubsubTopic, SingleShardInfo } from "@waku/interfaces"; import { WakuMessage } from "@waku/proto"; import { Logger, singleShardInfoToPubsubTopic } from "@waku/utils"; -import { generatePrivateKey } from "./crypto/utils.js"; import { DecodedMessage } from "./decoded_message.js"; import { decryptAsymmetric, encryptAsymmetric, postCipher, preCipher -} from "./encryption.js"; -import { OneMillion, Version } from "./misc.js"; +} from "./waku_payload.js"; -export { - decryptAsymmetric, - encryptAsymmetric, - postCipher, - preCipher, - generatePrivateKey -}; +import { + generatePrivateKey, + getPublicKey, + OneMillion, + Version +} from "./index.js"; + +export { generatePrivateKey, getPublicKey }; +export type { Encoder, Decoder, DecodedMessage }; const log = new Logger("message-encryption:ecies"); diff --git a/packages/message-encryption/src/index.ts b/packages/message-encryption/src/index.ts index 765c85dfc3..1bcc3934d7 100644 --- a/packages/message-encryption/src/index.ts +++ b/packages/message-encryption/src/index.ts @@ -5,9 +5,17 @@ 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 * as crypto from "./crypto"; + +export const Version = 1; + +export type Signature = { + signature: Uint8Array; + publicKey: Uint8Array | undefined; +}; diff --git a/packages/message-encryption/src/symmetric.ts b/packages/message-encryption/src/symmetric.ts index 9854f5c665..137acacc07 100644 --- a/packages/message-encryption/src/symmetric.ts +++ b/packages/message-encryption/src/symmetric.ts @@ -13,23 +13,18 @@ import type { import { WakuMessage } from "@waku/proto"; import { Logger, singleShardInfoToPubsubTopic } from "@waku/utils"; -import { generateSymmetricKey } from "./crypto/utils.js"; import { DecodedMessage } from "./decoded_message.js"; import { decryptSymmetric, encryptSymmetric, postCipher, preCipher -} from "./encryption.js"; -import { OneMillion, Version } from "./misc.js"; +} from "./waku_payload.js"; -export { - decryptSymmetric, - encryptSymmetric, - postCipher, - preCipher, - generateSymmetricKey -}; +import { generateSymmetricKey, OneMillion, Version } from "./index.js"; + +export { generateSymmetricKey }; +export type { DecodedMessage, Encoder, Decoder }; const log = new Logger("message-encryption:symmetric"); diff --git a/packages/message-encryption/src/encryption.spec.ts b/packages/message-encryption/src/waku_payload.spec.ts similarity index 97% rename from packages/message-encryption/src/encryption.spec.ts rename to packages/message-encryption/src/waku_payload.spec.ts index 67e0ca13d8..379b068197 100644 --- a/packages/message-encryption/src/encryption.spec.ts +++ b/packages/message-encryption/src/waku_payload.spec.ts @@ -9,9 +9,9 @@ import { encryptSymmetric, postCipher, preCipher -} from "./encryption.js"; +} from "./waku_payload.js"; -describe("Waku Encryption", function () { +describe("Waku Payload", function () { this.timeout(20000); it("Asymmetric encrypt & decrypt", async function () { await fc.assert( diff --git a/packages/message-encryption/src/encryption.ts b/packages/message-encryption/src/waku_payload.ts similarity index 96% rename from packages/message-encryption/src/encryption.ts rename to packages/message-encryption/src/waku_payload.ts index de0b2ac0bb..8da80da4be 100644 --- a/packages/message-encryption/src/encryption.ts +++ b/packages/message-encryption/src/waku_payload.ts @@ -1,14 +1,12 @@ import * as secp from "@noble/secp256k1"; import { concat, hexToBytes } from "@waku/utils/bytes"; -import { - ecies, - keccak256, - randomBytes, - sign, - symmetric -} from "./crypto/index.js"; -import { Symmetric } from "./misc.js"; +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"; const FlagsLength = 1; const FlagMask = 3; // 0011 @@ -212,11 +210,6 @@ export async function preCipher( return envelope; } -type Signature = { - signature: Uint8Array; - publicKey: Uint8Array | undefined; -}; - /** * Decode a decrypted payload. * diff --git a/packages/tests/tests/ephemeral.node.spec.ts b/packages/tests/tests/ephemeral.node.spec.ts index b8c0115e3d..3f301b9b53 100644 --- a/packages/tests/tests/ephemeral.node.spec.ts +++ b/packages/tests/tests/ephemeral.node.spec.ts @@ -6,16 +6,14 @@ import { } from "@waku/core"; import { IFilterSubscription, Protocols } from "@waku/interfaces"; import type { LightNode } from "@waku/interfaces"; -import { - generatePrivateKey, - generateSymmetricKey, - getPublicKey -} from "@waku/message-encryption"; import { createDecoder as eciesDecoder, - createEncoder as eciesEncoder + createEncoder as eciesEncoder, + generatePrivateKey, + getPublicKey } from "@waku/message-encryption/ecies"; import { + generateSymmetricKey, createDecoder as symDecoder, createEncoder as symEncoder } from "@waku/message-encryption/symmetric"; diff --git a/packages/tests/tests/filter/subscribe.node.spec.ts b/packages/tests/tests/filter/subscribe.node.spec.ts index 68b89e3d72..5853158221 100644 --- a/packages/tests/tests/filter/subscribe.node.spec.ts +++ b/packages/tests/tests/filter/subscribe.node.spec.ts @@ -6,13 +6,7 @@ import { } from "@waku/core"; import type { IFilterSubscription, LightNode } from "@waku/interfaces"; import { Protocols } from "@waku/interfaces"; -import { - ecies, - generatePrivateKey, - generateSymmetricKey, - getPublicKey, - symmetric -} from "@waku/message-encryption"; +import { ecies, symmetric } from "@waku/message-encryption"; import { utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; @@ -73,8 +67,8 @@ describe("Waku Filter V2: Subscribe", function () { }); it("Subscribe and receive ecies encrypted messages via lightPush", async function () { - const privateKey = generatePrivateKey(); - const publicKey = getPublicKey(privateKey); + const privateKey = ecies.generatePrivateKey(); + const publicKey = ecies.getPublicKey(privateKey); const encoder = ecies.createEncoder({ contentTopic: TestContentTopic, publicKey @@ -95,7 +89,7 @@ describe("Waku Filter V2: Subscribe", function () { }); it("Subscribe and receive symmetrically encrypted messages via lightPush", async function () { - const symKey = generateSymmetricKey(); + const symKey = symmetric.generateSymmetricKey(); const encoder = symmetric.createEncoder({ contentTopic: TestContentTopic, symKey diff --git a/packages/tests/tests/relay/index.node.spec.ts b/packages/tests/tests/relay/index.node.spec.ts index d6bb19fcff..31f955ab7c 100644 --- a/packages/tests/tests/relay/index.node.spec.ts +++ b/packages/tests/tests/relay/index.node.spec.ts @@ -1,17 +1,15 @@ import { createDecoder, createEncoder, DecodedMessage } from "@waku/core"; import { RelayNode } from "@waku/interfaces"; -import { - generatePrivateKey, - generateSymmetricKey, - getPublicKey -} from "@waku/message-encryption"; import { createDecoder as createEciesDecoder, - createEncoder as createEciesEncoder + createEncoder as createEciesEncoder, + generatePrivateKey, + getPublicKey } from "@waku/message-encryption/ecies"; import { createDecoder as createSymDecoder, - createEncoder as createSymEncoder + createEncoder as createSymEncoder, + generateSymmetricKey } from "@waku/message-encryption/symmetric"; import { createRelayNode } from "@waku/sdk"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; diff --git a/packages/tests/tests/store/index.node.spec.ts b/packages/tests/tests/store/index.node.spec.ts index c2347e54e0..78429d3efe 100644 --- a/packages/tests/tests/store/index.node.spec.ts +++ b/packages/tests/tests/store/index.node.spec.ts @@ -6,18 +6,16 @@ import { } from "@waku/core"; import type { IMessage, LightNode } from "@waku/interfaces"; import { Protocols } from "@waku/interfaces"; -import { - generatePrivateKey, - generateSymmetricKey, - getPublicKey -} from "@waku/message-encryption"; import { createDecoder as createEciesDecoder, - createEncoder as createEciesEncoder + createEncoder as createEciesEncoder, + generatePrivateKey, + getPublicKey } from "@waku/message-encryption/ecies"; import { createDecoder as createSymDecoder, - createEncoder as createSymEncoder + createEncoder as createSymEncoder, + generateSymmetricKey } from "@waku/message-encryption/symmetric"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; diff --git a/packages/tests/tests/waku.node.spec.ts b/packages/tests/tests/waku.node.spec.ts index e7aa69f176..6b399718fc 100644 --- a/packages/tests/tests/waku.node.spec.ts +++ b/packages/tests/tests/waku.node.spec.ts @@ -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 + createEncoder, + generateSymmetricKey } from "@waku/message-encryption/symmetric"; import { createLightNode,