diff --git a/.changeset/sweet-coins-jump.md b/.changeset/sweet-coins-jump.md new file mode 100644 index 00000000..cd6cdf80 --- /dev/null +++ b/.changeset/sweet-coins-jump.md @@ -0,0 +1,6 @@ +--- +"@xmtp/content-type-remote-attachment": patch +"@xmtp/xmtp-js": patch +--- + +Fix encryption dependency diff --git a/.github/workflows/encryption.yml b/.github/workflows/encryption.yml deleted file mode 100644 index eb43b4dd..00000000 --- a/.github/workflows/encryption.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: Encryption - -on: - push: - branches: - - main - - pull_request: - paths: - - "shared/encryption/**" - - ".github/workflows/encryption.yml" - - ".node-version" - - ".nvmrc" - - ".yarnrc.yml" - - "turbo.json" - -jobs: - typecheck: - name: Typecheck - runs-on: warp-ubuntu-latest-x64-8x - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version-file: ".nvmrc" - cache: "yarn" - env: - SKIP_YARN_COREPACK_CHECK: "1" - - name: Enable corepack - run: corepack enable - - name: Install dependencies - run: yarn - - name: Typecheck - run: yarn turbo run typecheck --filter='./shared/encryption' - - test: - name: Test - runs-on: warp-ubuntu-latest-x64-8x - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version-file: ".nvmrc" - cache: "yarn" - env: - SKIP_YARN_COREPACK_CHECK: "1" - - name: Enable corepack - run: corepack enable - - name: Install dependencies - run: yarn - - name: Start dev environment - run: ./dev/up - - name: Sleep for 5 seconds - run: sleep 5s - - name: Run tests - run: yarn turbo run test --filter='./shared/encryption' - - build: - name: Build - runs-on: warp-ubuntu-latest-x64-8x - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version-file: ".nvmrc" - cache: "yarn" - env: - SKIP_YARN_COREPACK_CHECK: "1" - - name: Enable corepack - run: corepack enable - - name: Install dependencies - run: yarn - - name: Build - run: yarn turbo run build --filter='./shared/encryption' diff --git a/content-types/content-type-remote-attachment/package.json b/content-types/content-type-remote-attachment/package.json index c0aae3d2..39f61420 100644 --- a/content-types/content-type-remote-attachment/package.json +++ b/content-types/content-type-remote-attachment/package.json @@ -65,11 +65,9 @@ "dependencies": { "@noble/secp256k1": "^1.7.1", "@xmtp/content-type-primitives": "^1.0.2", - "@xmtp/encryption": "workspace:*", "@xmtp/proto": "^3.61.1" }, "devDependencies": { - "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.1", "@types/node": "^20.16.11", diff --git a/content-types/content-type-remote-attachment/rollup.config.js b/content-types/content-type-remote-attachment/rollup.config.js index b11bf152..14dd0a59 100644 --- a/content-types/content-type-remote-attachment/rollup.config.js +++ b/content-types/content-type-remote-attachment/rollup.config.js @@ -1,4 +1,3 @@ -import { nodeResolve } from "@rollup/plugin-node-resolve"; import terser from "@rollup/plugin-terser"; import typescript from "@rollup/plugin-typescript"; import { resolveExtensions } from "@xmtp/rollup-plugin-resolve-extensions"; @@ -14,9 +13,6 @@ const plugins = [ filesize({ showMinifiedSize: false, }), - nodeResolve({ - resolveOnly: ["@xmtp/encryption"], - }), ]; const external = [ diff --git a/content-types/content-type-remote-attachment/src/RemoteAttachment.ts b/content-types/content-type-remote-attachment/src/RemoteAttachment.ts index f4fe4c35..703e132f 100644 --- a/content-types/content-type-remote-attachment/src/RemoteAttachment.ts +++ b/content-types/content-type-remote-attachment/src/RemoteAttachment.ts @@ -5,8 +5,8 @@ import { type ContentCodec, type EncodedContent, } from "@xmtp/content-type-primitives"; -import { Ciphertext, crypto, decrypt, encrypt } from "@xmtp/encryption"; import { content as proto } from "@xmtp/proto"; +import { Ciphertext, crypto, decrypt, encrypt } from "./encryption"; export const ContentTypeRemoteAttachment = new ContentTypeId({ authorityId: "xmtp.org", diff --git a/shared/encryption/src/Ciphertext.ts b/content-types/content-type-remote-attachment/src/encryption/Ciphertext.ts similarity index 100% rename from shared/encryption/src/Ciphertext.ts rename to content-types/content-type-remote-attachment/src/encryption/Ciphertext.ts diff --git a/shared/encryption/src/crypto.browser.ts b/content-types/content-type-remote-attachment/src/encryption/crypto.browser.ts similarity index 100% rename from shared/encryption/src/crypto.browser.ts rename to content-types/content-type-remote-attachment/src/encryption/crypto.browser.ts diff --git a/shared/encryption/src/crypto.ts b/content-types/content-type-remote-attachment/src/encryption/crypto.ts similarity index 100% rename from shared/encryption/src/crypto.ts rename to content-types/content-type-remote-attachment/src/encryption/crypto.ts diff --git a/shared/encryption/src/encryption.ts b/content-types/content-type-remote-attachment/src/encryption/encryption.ts similarity index 97% rename from shared/encryption/src/encryption.ts rename to content-types/content-type-remote-attachment/src/encryption/encryption.ts index ed3124f5..3574b4f2 100644 --- a/shared/encryption/src/encryption.ts +++ b/content-types/content-type-remote-attachment/src/encryption/encryption.ts @@ -1,6 +1,6 @@ import type { ciphertext } from "@xmtp/proto"; -import Ciphertext, { AESGCMNonceSize, KDFSaltSize } from "@/Ciphertext"; -import crypto from "@/crypto"; +import Ciphertext, { AESGCMNonceSize, KDFSaltSize } from "./Ciphertext"; +import crypto from "./crypto"; const hkdfNoInfo = new Uint8Array().buffer; const hkdfNoSalt = new Uint8Array().buffer; diff --git a/shared/encryption/src/index.ts b/content-types/content-type-remote-attachment/src/encryption/index.ts similarity index 100% rename from shared/encryption/src/index.ts rename to content-types/content-type-remote-attachment/src/encryption/index.ts diff --git a/eslint.config.js b/eslint.config.js index 78fe8baa..4213b7cc 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -82,7 +82,7 @@ export default tseslint.config( { selector: "ImportDeclaration[source.value=/^(node:)?crypto$/]", message: - "Do not import directly from `crypto`, use `@xmtp/encryption` instead.", + "Do not import directly from `crypto`, use `@/encryption` instead.", }, ], }, diff --git a/sdks/js-sdk/bench/helpers.ts b/sdks/js-sdk/bench/helpers.ts index 4621c773..d88e33f1 100644 --- a/sdks/js-sdk/bench/helpers.ts +++ b/sdks/js-sdk/bench/helpers.ts @@ -1,8 +1,8 @@ -import { crypto } from "@xmtp/encryption"; import type Benchmark from "benchmark"; import { cycle, save, suite } from "benny"; import type { Config } from "benny/lib/internal/common-types"; import { PrivateKeyBundleV1 } from "@/crypto/PrivateKeyBundle"; +import { crypto } from "@/encryption"; import { newWallet } from "@test/helpers"; const MAX_RANDOM_BYTES_SIZE = 65536; diff --git a/sdks/js-sdk/package.json b/sdks/js-sdk/package.json index 8caf45a6..ac05610f 100644 --- a/sdks/js-sdk/package.json +++ b/sdks/js-sdk/package.json @@ -97,7 +97,6 @@ "@xmtp/consent-proof-signature": "^0.1.3", "@xmtp/content-type-primitives": "^1.0.1", "@xmtp/content-type-text": "^1.0.0", - "@xmtp/encryption": "workspace:*", "@xmtp/proto": "^3.68.0", "@xmtp/user-preferences-bindings-wasm": "^0.3.6", "async-mutex": "^0.5.0", @@ -108,7 +107,6 @@ "devDependencies": { "@metamask/providers": "^17.1.1", "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.1", "@types/benchmark": "^2.1.5", diff --git a/sdks/js-sdk/rollup.config.js b/sdks/js-sdk/rollup.config.js index c5b71421..8d19c44b 100644 --- a/sdks/js-sdk/rollup.config.js +++ b/sdks/js-sdk/rollup.config.js @@ -1,5 +1,4 @@ import json from "@rollup/plugin-json"; -import { nodeResolve } from "@rollup/plugin-node-resolve"; import terser from "@rollup/plugin-terser"; import typescript from "@rollup/plugin-typescript"; import { resolveExtensions } from "@xmtp/rollup-plugin-resolve-extensions"; @@ -36,9 +35,6 @@ const plugins = [ json({ preferConst: true, }), - nodeResolve({ - resolveOnly: ["@xmtp/encryption"], - }), ]; export default defineConfig([ diff --git a/sdks/js-sdk/src/Invitation.ts b/sdks/js-sdk/src/Invitation.ts index aae6b5c6..0902ff1d 100644 --- a/sdks/js-sdk/src/Invitation.ts +++ b/sdks/js-sdk/src/Invitation.ts @@ -1,6 +1,6 @@ -import { Ciphertext, crypto, decrypt, encrypt } from "@xmtp/encryption"; import { invitation, type messageApi } from "@xmtp/proto"; import Long from "long"; +import { Ciphertext, crypto, decrypt, encrypt } from "@/encryption"; import { dateToNs } from "@/utils/date"; import { buildDirectMessageTopicV2 } from "@/utils/topic"; import type { PrivateKeyBundleV2 } from "./crypto/PrivateKeyBundle"; diff --git a/sdks/js-sdk/src/Message.ts b/sdks/js-sdk/src/Message.ts index a9ed17a1..fcc94923 100644 --- a/sdks/js-sdk/src/Message.ts +++ b/sdks/js-sdk/src/Message.ts @@ -1,9 +1,9 @@ import type { ContentTypeId } from "@xmtp/content-type-primitives"; -import { Ciphertext, sha256 } from "@xmtp/encryption"; import { message as proto, type conversationReference } from "@xmtp/proto"; import Long from "long"; import { PublicKey } from "@/crypto/PublicKey"; import { PublicKeyBundle } from "@/crypto/PublicKeyBundle"; +import { Ciphertext, sha256 } from "@/encryption"; import type Client from "./Client"; import { ConversationV1, diff --git a/sdks/js-sdk/src/PreparedMessage.ts b/sdks/js-sdk/src/PreparedMessage.ts index ea020fed..4f568196 100644 --- a/sdks/js-sdk/src/PreparedMessage.ts +++ b/sdks/js-sdk/src/PreparedMessage.ts @@ -1,5 +1,5 @@ -import { sha256 } from "@xmtp/encryption"; import type { Envelope } from "@xmtp/proto/ts/dist/types/message_api/v1/message_api.pb"; +import { sha256 } from "@/encryption"; import { bytesToHex } from "./crypto/utils"; import type { DecodedMessage } from "./Message"; diff --git a/sdks/js-sdk/src/conversations/Conversation.ts b/sdks/js-sdk/src/conversations/Conversation.ts index 48222adc..bcf8b9e4 100644 --- a/sdks/js-sdk/src/conversations/Conversation.ts +++ b/sdks/js-sdk/src/conversations/Conversation.ts @@ -1,5 +1,4 @@ import { ContentTypeText } from "@xmtp/content-type-text"; -import { sha256 } from "@xmtp/encryption"; import { message, content as proto, @@ -22,6 +21,7 @@ import { SignedPublicKeyBundle, } from "@/crypto/PublicKeyBundle"; import Signature from "@/crypto/Signature"; +import { sha256 } from "@/encryption"; import type { InvitationContext } from "@/Invitation"; import { DecodedMessage, MessageV1, MessageV2 } from "@/Message"; import { PreparedMessage } from "@/PreparedMessage"; diff --git a/sdks/js-sdk/src/crypto/PrivateKey.ts b/sdks/js-sdk/src/crypto/PrivateKey.ts index 5f292a6e..f38fecd6 100644 --- a/sdks/js-sdk/src/crypto/PrivateKey.ts +++ b/sdks/js-sdk/src/crypto/PrivateKey.ts @@ -1,7 +1,7 @@ import * as secp from "@noble/secp256k1"; -import { decrypt, encrypt, sha256, type Ciphertext } from "@xmtp/encryption"; import { privateKey } from "@xmtp/proto"; import Long from "long"; +import { decrypt, encrypt, sha256, type Ciphertext } from "@/encryption"; import { PublicKey, SignedPublicKey, UnsignedPublicKey } from "./PublicKey"; import Signature, { ecdsaSignerKey, diff --git a/sdks/js-sdk/src/crypto/PublicKey.ts b/sdks/js-sdk/src/crypto/PublicKey.ts index aed402ae..f13cf23a 100644 --- a/sdks/js-sdk/src/crypto/PublicKey.ts +++ b/sdks/js-sdk/src/crypto/PublicKey.ts @@ -1,8 +1,8 @@ import * as secp from "@noble/secp256k1"; -import { sha256 } from "@xmtp/encryption"; import { publicKey } from "@xmtp/proto"; import Long from "long"; import { hashMessage, hexToBytes, type Hex } from "viem"; +import { sha256 } from "@/encryption"; import type { Signer } from "@/types/Signer"; import Signature, { WalletSigner } from "./Signature"; import { computeAddress, equalBytes, splitSignature } from "./utils"; diff --git a/sdks/js-sdk/src/crypto/SignedEciesCiphertext.ts b/sdks/js-sdk/src/crypto/SignedEciesCiphertext.ts index 20c45173..8b8df1b7 100644 --- a/sdks/js-sdk/src/crypto/SignedEciesCiphertext.ts +++ b/sdks/js-sdk/src/crypto/SignedEciesCiphertext.ts @@ -1,5 +1,5 @@ -import { sha256 } from "@xmtp/encryption"; import { ciphertext } from "@xmtp/proto"; +import { sha256 } from "@/encryption"; import type { PrivateKey, SignedPrivateKey } from "./PrivateKey"; import type { PublicKey, SignedPublicKey } from "./PublicKey"; import Signature from "./Signature"; diff --git a/sdks/js-sdk/src/crypto/ecies.ts b/sdks/js-sdk/src/crypto/ecies.ts index 1e7d31c5..d40e52ce 100644 --- a/sdks/js-sdk/src/crypto/ecies.ts +++ b/sdks/js-sdk/src/crypto/ecies.ts @@ -3,8 +3,8 @@ * `elliptic` is a CommonJS module and has issues with named imports * DO NOT CHANGE THIS TO A NAMED IMPORT */ -import { crypto } from "@xmtp/encryption"; import elliptic from "elliptic"; +import { crypto } from "@/encryption"; const EC = elliptic.ec; const ec = new EC("secp256k1"); diff --git a/sdks/js-sdk/src/encryption/Ciphertext.ts b/sdks/js-sdk/src/encryption/Ciphertext.ts new file mode 100644 index 00000000..02fc66fd --- /dev/null +++ b/sdks/js-sdk/src/encryption/Ciphertext.ts @@ -0,0 +1,43 @@ +import { ciphertext } from "@xmtp/proto"; + +export const AESKeySize = 32; // bytes +export const KDFSaltSize = 32; // bytes +// AES-GCM defaults from https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams +export const AESGCMNonceSize = 12; // property iv +export const AESGCMTagLength = 16; // property tagLength + +// Ciphertext packages the encrypted ciphertext with the salt and nonce used to produce it. +// salt and nonce are not secret, and should be transmitted/stored along with the encrypted ciphertext. +export default class Ciphertext implements ciphertext.Ciphertext { + aes256GcmHkdfSha256: ciphertext.Ciphertext_Aes256gcmHkdfsha256 | undefined; + + constructor(obj: ciphertext.Ciphertext) { + if (!obj.aes256GcmHkdfSha256) { + throw new Error("invalid ciphertext"); + } + if (obj.aes256GcmHkdfSha256.payload.length < AESGCMTagLength) { + throw new Error( + `invalid ciphertext ciphertext length: ${obj.aes256GcmHkdfSha256.payload.length}`, + ); + } + if (obj.aes256GcmHkdfSha256.hkdfSalt.length !== KDFSaltSize) { + throw new Error( + `invalid ciphertext salt length: ${obj.aes256GcmHkdfSha256.hkdfSalt.length}`, + ); + } + if (obj.aes256GcmHkdfSha256.gcmNonce.length !== AESGCMNonceSize) { + throw new Error( + `invalid ciphertext nonce length: ${obj.aes256GcmHkdfSha256.gcmNonce.length}`, + ); + } + this.aes256GcmHkdfSha256 = obj.aes256GcmHkdfSha256; + } + + toBytes(): Uint8Array { + return ciphertext.Ciphertext.encode(this).finish(); + } + + static fromBytes(bytes: Uint8Array): Ciphertext { + return new Ciphertext(ciphertext.Ciphertext.decode(bytes)); + } +} diff --git a/sdks/js-sdk/src/encryption/crypto.browser.ts b/sdks/js-sdk/src/encryption/crypto.browser.ts new file mode 100644 index 00000000..e34bab87 --- /dev/null +++ b/sdks/js-sdk/src/encryption/crypto.browser.ts @@ -0,0 +1,5 @@ +/*********************************************************************************************** + * DO NOT IMPORT THIS FILE DIRECTLY + ***********************************************************************************************/ +const crypto = window.crypto; +export default crypto; diff --git a/sdks/js-sdk/src/encryption/crypto.ts b/sdks/js-sdk/src/encryption/crypto.ts new file mode 100644 index 00000000..9f6a7cc7 --- /dev/null +++ b/sdks/js-sdk/src/encryption/crypto.ts @@ -0,0 +1,4 @@ +import { webcrypto } from "node:crypto"; + +const crypto = webcrypto; +export default crypto; diff --git a/sdks/js-sdk/src/encryption/encryption.ts b/sdks/js-sdk/src/encryption/encryption.ts new file mode 100644 index 00000000..3574b4f2 --- /dev/null +++ b/sdks/js-sdk/src/encryption/encryption.ts @@ -0,0 +1,135 @@ +import type { ciphertext } from "@xmtp/proto"; +import Ciphertext, { AESGCMNonceSize, KDFSaltSize } from "./Ciphertext"; +import crypto from "./crypto"; + +const hkdfNoInfo = new Uint8Array().buffer; +const hkdfNoSalt = new Uint8Array().buffer; + +// This is a variation of https://github.com/paulmillr/noble-secp256k1/blob/main/index.ts#L1378-L1388 +// that uses `digest('SHA-256', bytes)` instead of `digest('SHA-256', bytes.buffer)` +// which seems to produce different results. +export async function sha256(bytes: Uint8Array): Promise { + return new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)); +} + +// symmetric authenticated encryption of plaintext using the secret; +// additionalData is used to protect un-encrypted parts of the message (header) +// in the authentication scope of the encryption. +export async function encrypt( + plain: Uint8Array, + secret: Uint8Array, + additionalData?: Uint8Array, +): Promise { + const salt = crypto.getRandomValues(new Uint8Array(KDFSaltSize)); + const nonce = crypto.getRandomValues(new Uint8Array(AESGCMNonceSize)); + const key = await hkdf(secret, salt); + const encrypted: ArrayBuffer = await crypto.subtle.encrypt( + aesGcmParams(nonce, additionalData), + key, + plain, + ); + return new Ciphertext({ + aes256GcmHkdfSha256: { + payload: new Uint8Array(encrypted), + hkdfSalt: salt, + gcmNonce: nonce, + }, + }); +} + +// symmetric authenticated decryption of the encrypted ciphertext using the secret and additionalData +export async function decrypt( + encrypted: Ciphertext | ciphertext.Ciphertext, + secret: Uint8Array, + additionalData?: Uint8Array, +): Promise { + if (!encrypted.aes256GcmHkdfSha256) { + throw new Error("invalid payload ciphertext"); + } + const key = await hkdf(secret, encrypted.aes256GcmHkdfSha256.hkdfSalt); + const decrypted: ArrayBuffer = await crypto.subtle.decrypt( + aesGcmParams(encrypted.aes256GcmHkdfSha256.gcmNonce, additionalData), + key, + encrypted.aes256GcmHkdfSha256.payload, + ); + return new Uint8Array(decrypted); +} + +// helper for building Web Crypto API encryption parameter structure +function aesGcmParams( + nonce: Uint8Array, + additionalData?: Uint8Array, +): AesGcmParams { + const spec: AesGcmParams = { + name: "AES-GCM", + iv: nonce, + }; + if (additionalData) { + spec.additionalData = additionalData; + } + return spec; +} + +// Derive AES-256-GCM key from a shared secret and salt. +// Returns crypto.CryptoKey suitable for the encrypt/decrypt API +async function hkdf(secret: Uint8Array, salt: Uint8Array): Promise { + const key = await crypto.subtle.importKey("raw", secret, "HKDF", false, [ + "deriveKey", + ]); + return crypto.subtle.deriveKey( + { name: "HKDF", hash: "SHA-256", salt, info: hkdfNoInfo }, + key, + { name: "AES-GCM", length: 256 }, + false, + ["encrypt", "decrypt"], + ); +} + +export async function hkdfHmacKey( + secret: Uint8Array, + info: Uint8Array, +): Promise { + const key = await crypto.subtle.importKey("raw", secret, "HKDF", false, [ + "deriveKey", + ]); + return crypto.subtle.deriveKey( + { name: "HKDF", hash: "SHA-256", salt: hkdfNoSalt, info }, + key, + { name: "HMAC", hash: "SHA-256", length: 256 }, + true, + ["sign", "verify"], + ); +} + +export async function generateHmacSignature( + secret: Uint8Array, + info: Uint8Array, + message: Uint8Array, +): Promise { + const key = await hkdfHmacKey(secret, info); + const signed = await crypto.subtle.sign("HMAC", key, message); + return new Uint8Array(signed); +} + +export async function verifyHmacSignature( + key: CryptoKey, + signature: Uint8Array, + message: Uint8Array, +): Promise { + return await crypto.subtle.verify("HMAC", key, signature, message); +} + +export async function exportHmacKey(key: CryptoKey): Promise { + const exported = await crypto.subtle.exportKey("raw", key); + return new Uint8Array(exported); +} + +export async function importHmacKey(key: Uint8Array): Promise { + return crypto.subtle.importKey( + "raw", + key, + { name: "HMAC", hash: "SHA-256", length: 256 }, + true, + ["sign", "verify"], + ); +} diff --git a/sdks/js-sdk/src/encryption/index.ts b/sdks/js-sdk/src/encryption/index.ts new file mode 100644 index 00000000..9bc0f254 --- /dev/null +++ b/sdks/js-sdk/src/encryption/index.ts @@ -0,0 +1,3 @@ +export { default as Ciphertext } from "./Ciphertext"; +export { default as crypto } from "./crypto"; +export * from "./encryption"; diff --git a/sdks/js-sdk/src/index.ts b/sdks/js-sdk/src/index.ts index 68ad609a..2cde96f4 100644 --- a/sdks/js-sdk/src/index.ts +++ b/sdks/js-sdk/src/index.ts @@ -6,7 +6,7 @@ export { PrivateKeyBundleV1, PrivateKeyBundleV2, } from "./crypto/PrivateKeyBundle"; -export { Ciphertext } from "@xmtp/encryption"; +export { Ciphertext } from "./encryption"; export { PublicKey, SignedPublicKey } from "./crypto/PublicKey"; export { PublicKeyBundle, @@ -21,7 +21,7 @@ export { hkdfHmacKey, importHmacKey, verifyHmacSignature, -} from "@xmtp/encryption"; +} from "./encryption"; export { default as Stream } from "./Stream"; export type { Signer } from "./types/Signer"; export type { diff --git a/sdks/js-sdk/src/keystore/InMemoryKeystore.ts b/sdks/js-sdk/src/keystore/InMemoryKeystore.ts index 71d93411..da656a6d 100644 --- a/sdks/js-sdk/src/keystore/InMemoryKeystore.ts +++ b/sdks/js-sdk/src/keystore/InMemoryKeystore.ts @@ -1,9 +1,3 @@ -import { - crypto, - exportHmacKey, - generateHmacSignature, - hkdfHmacKey, -} from "@xmtp/encryption"; import { keystore, privatePreferences, @@ -27,6 +21,12 @@ import { userPreferencesEncrypt, } from "@/crypto/selfEncryption"; import { bytesToHex } from "@/crypto/utils"; +import { + crypto, + exportHmacKey, + generateHmacSignature, + hkdfHmacKey, +} from "@/encryption"; import { InvitationV1, SealedInvitation } from "@/Invitation"; import { PrivatePreferencesStore, diff --git a/sdks/js-sdk/src/keystore/encryption.ts b/sdks/js-sdk/src/keystore/encryption.ts index 434fccf6..6c37a6c9 100644 --- a/sdks/js-sdk/src/keystore/encryption.ts +++ b/sdks/js-sdk/src/keystore/encryption.ts @@ -1,7 +1,7 @@ -import { decrypt, encrypt } from "@xmtp/encryption"; import type { ciphertext } from "@xmtp/proto"; import type { PrivateKeyBundleV1 } from "@/crypto/PrivateKeyBundle"; import type { PublicKeyBundle } from "@/crypto/PublicKeyBundle"; +import { decrypt, encrypt } from "@/encryption"; export const decryptV1 = async ( myKeys: PrivateKeyBundleV1, diff --git a/sdks/js-sdk/src/keystore/providers/NetworkKeyManager.ts b/sdks/js-sdk/src/keystore/providers/NetworkKeyManager.ts index 25c724c7..07818a58 100644 --- a/sdks/js-sdk/src/keystore/providers/NetworkKeyManager.ts +++ b/sdks/js-sdk/src/keystore/providers/NetworkKeyManager.ts @@ -1,4 +1,3 @@ -import { Ciphertext, crypto, decrypt, encrypt } from "@xmtp/encryption"; import { privateKey as proto } from "@xmtp/proto"; import { getAddress, hexToBytes, verifyMessage, type Hex } from "viem"; import LocalAuthenticator from "@/authn/LocalAuthenticator"; @@ -9,6 +8,7 @@ import { PrivateKeyBundleV2, } from "@/crypto/PrivateKeyBundle"; import { bytesToHex } from "@/crypto/utils"; +import { Ciphertext, crypto, decrypt, encrypt } from "@/encryption"; import type TopicPersistence from "@/keystore/persistence/TopicPersistence"; import type { Signer } from "@/types/Signer"; diff --git a/sdks/js-sdk/test/Invitation.test.ts b/sdks/js-sdk/test/Invitation.test.ts index d19ee02d..bbd4721e 100644 --- a/sdks/js-sdk/test/Invitation.test.ts +++ b/sdks/js-sdk/test/Invitation.test.ts @@ -1,7 +1,7 @@ -import { Ciphertext, crypto } from "@xmtp/encryption"; import Long from "long"; import { NoMatchingPreKeyError } from "@/crypto/errors"; import { PrivateKeyBundleV2 } from "@/crypto/PrivateKeyBundle"; +import { Ciphertext, crypto } from "@/encryption"; import { InvitationV1, SealedInvitation, diff --git a/sdks/js-sdk/test/Message.test.ts b/sdks/js-sdk/test/Message.test.ts index 48acf4f5..1cc43590 100644 --- a/sdks/js-sdk/test/Message.test.ts +++ b/sdks/js-sdk/test/Message.test.ts @@ -1,5 +1,4 @@ import { ContentTypeText } from "@xmtp/content-type-text"; -import { sha256 } from "@xmtp/encryption"; import type { Wallet } from "ethers"; import { createWalletClient, http } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; @@ -8,6 +7,7 @@ import Client from "@/Client"; import { ConversationV1 } from "@/conversations/Conversation"; import { PrivateKeyBundleV1 } from "@/crypto/PrivateKeyBundle"; import { bytesToHex, equalBytes } from "@/crypto/utils"; +import { sha256 } from "@/encryption"; import { KeystoreError } from "@/keystore/errors"; import InMemoryKeystore from "@/keystore/InMemoryKeystore"; import InMemoryPersistence from "@/keystore/persistence/InMemoryPersistence"; diff --git a/sdks/js-sdk/test/crypto/SignedEciesCiphertext.test.ts b/sdks/js-sdk/test/crypto/SignedEciesCiphertext.test.ts index a9999a33..3a5469f6 100644 --- a/sdks/js-sdk/test/crypto/SignedEciesCiphertext.test.ts +++ b/sdks/js-sdk/test/crypto/SignedEciesCiphertext.test.ts @@ -1,8 +1,8 @@ -import { crypto } from "@xmtp/encryption"; import { encrypt, getPublic } from "@/crypto/ecies"; import { PrivateKeyBundleV1 } from "@/crypto/PrivateKeyBundle"; import SignedEciesCiphertext from "@/crypto/SignedEciesCiphertext"; import { equalBytes } from "@/crypto/utils"; +import { crypto } from "@/encryption"; import { newWallet } from "@test/helpers"; describe("SignedEciesCiphertext", () => { diff --git a/sdks/js-sdk/test/crypto/index.test.ts b/sdks/js-sdk/test/crypto/index.test.ts index 08cfaf73..8a1f4b49 100644 --- a/sdks/js-sdk/test/crypto/index.test.ts +++ b/sdks/js-sdk/test/crypto/index.test.ts @@ -1,8 +1,8 @@ -import { crypto, decrypt, encrypt } from "@xmtp/encryption"; import { assert } from "vitest"; import { PrivateKey } from "@/crypto/PrivateKey"; import { PrivateKeyBundleV1 } from "@/crypto/PrivateKeyBundle"; import { PublicKeyBundle } from "@/crypto/PublicKeyBundle"; +import { crypto, decrypt, encrypt } from "@/encryption"; describe("Crypto", function () { it("signs keys and verifies signatures", async function () { diff --git a/sdks/js-sdk/test/keystore/InMemoryKeystore.test.ts b/sdks/js-sdk/test/keystore/InMemoryKeystore.test.ts index c7b422e5..b3c5b59a 100644 --- a/sdks/js-sdk/test/keystore/InMemoryKeystore.test.ts +++ b/sdks/js-sdk/test/keystore/InMemoryKeystore.test.ts @@ -1,9 +1,3 @@ -import { - generateHmacSignature, - hkdfHmacKey, - importHmacKey, - verifyHmacSignature, -} from "@xmtp/encryption"; import { keystore, privateKey } from "@xmtp/proto"; import type { CreateInviteResponse } from "@xmtp/proto/ts/dist/types/keystore_api/v1/keystore.pb"; import Long from "long"; @@ -16,6 +10,12 @@ import { } from "@/crypto/PrivateKeyBundle"; import { SignedPublicKeyBundle } from "@/crypto/PublicKeyBundle"; import { equalBytes } from "@/crypto/utils"; +import { + generateHmacSignature, + hkdfHmacKey, + importHmacKey, + verifyHmacSignature, +} from "@/encryption"; import { InvitationV1, SealedInvitation, diff --git a/sdks/js-sdk/test/keystore/conversationStores.test.ts b/sdks/js-sdk/test/keystore/conversationStores.test.ts index 4503fc5f..7315dc9b 100644 --- a/sdks/js-sdk/test/keystore/conversationStores.test.ts +++ b/sdks/js-sdk/test/keystore/conversationStores.test.ts @@ -1,4 +1,4 @@ -import { crypto } from "@xmtp/encryption"; +import { crypto } from "@/encryption"; import { V1Store, V2Store, diff --git a/sdks/js-sdk/test/keystore/encryption.test.ts b/sdks/js-sdk/test/keystore/encryption.test.ts index 07a39445..4a061ebe 100644 --- a/sdks/js-sdk/test/keystore/encryption.test.ts +++ b/sdks/js-sdk/test/keystore/encryption.test.ts @@ -1,7 +1,7 @@ -import { Ciphertext } from "@xmtp/encryption"; import { Wallet } from "ethers"; import { PrivateKeyBundleV1 } from "@/crypto/PrivateKeyBundle"; import { equalBytes } from "@/crypto/utils"; +import { Ciphertext } from "@/encryption"; import { decryptV1, encryptV1 } from "@/keystore/encryption"; import InMemoryKeystore from "@/keystore/InMemoryKeystore"; import InMemoryPersistence from "@/keystore/persistence/InMemoryPersistence"; diff --git a/sdks/js-sdk/test/keystore/persistence/EncryptedPersistence.test.ts b/sdks/js-sdk/test/keystore/persistence/EncryptedPersistence.test.ts index eece0aa0..b16b7d8e 100644 --- a/sdks/js-sdk/test/keystore/persistence/EncryptedPersistence.test.ts +++ b/sdks/js-sdk/test/keystore/persistence/EncryptedPersistence.test.ts @@ -1,7 +1,7 @@ -import { crypto } from "@xmtp/encryption"; import type { PrivateKey } from "@/crypto/PrivateKey"; import { PrivateKeyBundleV1 } from "@/crypto/PrivateKeyBundle"; import SignedEciesCiphertext from "@/crypto/SignedEciesCiphertext"; +import { crypto } from "@/encryption"; import EncryptedPersistence from "@/keystore/persistence/EncryptedPersistence"; import InMemoryPersistence from "@/keystore/persistence/InMemoryPersistence"; diff --git a/sdks/js-sdk/test/keystore/privatePreferencesStore.test.ts b/sdks/js-sdk/test/keystore/privatePreferencesStore.test.ts index 7b944126..7e83344a 100644 --- a/sdks/js-sdk/test/keystore/privatePreferencesStore.test.ts +++ b/sdks/js-sdk/test/keystore/privatePreferencesStore.test.ts @@ -1,5 +1,5 @@ -import { crypto } from "@xmtp/encryption"; import type { PrivatePreferencesAction } from "@xmtp/proto/ts/dist/types/message_contents/private_preferences.pb"; +import { crypto } from "@/encryption"; import InMemoryPersistence from "@/keystore/persistence/InMemoryPersistence"; import { PrivatePreferencesStore } from "@/keystore/privatePreferencesStore"; diff --git a/sdks/js-sdk/test/keystore/providers/NetworkKeystoreProvider.test.ts b/sdks/js-sdk/test/keystore/providers/NetworkKeystoreProvider.test.ts index 666bb6a1..0348ea56 100644 --- a/sdks/js-sdk/test/keystore/providers/NetworkKeystoreProvider.test.ts +++ b/sdks/js-sdk/test/keystore/providers/NetworkKeystoreProvider.test.ts @@ -1,10 +1,10 @@ -import { crypto, encrypt } from "@xmtp/encryption"; import { privateKey } from "@xmtp/proto"; import { hexToBytes, type Hex } from "viem"; import { vi } from "vitest"; import ApiClient, { ApiUrls } from "@/ApiClient"; import LocalAuthenticator from "@/authn/LocalAuthenticator"; import { PrivateKeyBundleV1 } from "@/crypto/PrivateKeyBundle"; +import { crypto, encrypt } from "@/encryption"; import TopicPersistence from "@/keystore/persistence/TopicPersistence"; import { KeystoreProviderUnavailableError } from "@/keystore/providers/errors"; import NetworkKeyManager, { diff --git a/sdks/js-sdk/test/utils/topic.test.ts b/sdks/js-sdk/test/utils/topic.test.ts index 425fc386..2266e699 100644 --- a/sdks/js-sdk/test/utils/topic.test.ts +++ b/sdks/js-sdk/test/utils/topic.test.ts @@ -1,4 +1,4 @@ -import { crypto } from "@xmtp/encryption"; +import { crypto } from "@/encryption"; import { buildContentTopic, buildDirectMessageTopicV2, diff --git a/shared/encryption/LICENSE b/shared/encryption/LICENSE deleted file mode 100644 index 11eedfd1..00000000 --- a/shared/encryption/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 XMTP (xmtp.org) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/shared/encryption/README.md b/shared/encryption/README.md deleted file mode 100644 index 8c57e74c..00000000 --- a/shared/encryption/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# XMTP Encryption - -This package provides private,shared encryption functions for use with XMTP. diff --git a/shared/encryption/package.json b/shared/encryption/package.json deleted file mode 100644 index 5b2f2181..00000000 --- a/shared/encryption/package.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "name": "@xmtp/encryption", - "version": "0.0.0", - "private": true, - "license": "MIT", - "author": "XMTP Labs ", - "type": "module", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "browser": "./dist/browser/index.js", - "import": "./dist/index.js", - "require": "./dist/index.cjs" - }, - "./node": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js", - "require": "./dist/index.cjs" - }, - "./browser": { - "types": "./dist/index.d.ts", - "default": "./dist/browser/index.js" - } - }, - "main": "dist/index.cjs", - "module": "dist/index.js", - "browser": "dist/browser/index.js", - "types": "dist/index.d.ts", - "files": [ - "dist" - ], - "scripts": { - "build": "yarn clean:dist && rollup -c", - "clean": "rimraf .turbo && yarn clean:dist && yarn clean:deps", - "clean:deps": "rimraf node_modules", - "clean:dist": "rimraf dist", - "test": "yarn test:node && yarn test:browser", - "test:browser": "vitest run --environment happy-dom", - "test:cov": "vitest run --coverage", - "test:node": "vitest run", - "typecheck": "tsc" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 3 chrome versions", - "last 3 firefox versions", - "last 3 safari versions" - ] - }, - "dependencies": { - "@xmtp/proto": "^3.68.0" - }, - "devDependencies": { - "@rollup/plugin-terser": "^0.4.4", - "@rollup/plugin-typescript": "^12.1.1", - "@types/node": "^20.16.11", - "@vitest/coverage-v8": "^2.1.3", - "@xmtp/rollup-plugin-resolve-extensions": "1.0.1", - "happy-dom": "^15.7.4", - "rimraf": "^6.0.1", - "rollup": "^4.24.0", - "rollup-plugin-dts": "^6.1.1", - "rollup-plugin-filesize": "^10.0.0", - "rollup-plugin-tsconfig-paths": "^1.5.2", - "typescript": "^5.6.3", - "vite": "^5.4.9", - "vite-tsconfig-paths": "^5.0.1", - "vitest": "^2.1.3" - }, - "packageManager": "yarn@4.5.0", - "engines": { - "node": ">=20" - } -} diff --git a/shared/encryption/rollup.config.js b/shared/encryption/rollup.config.js deleted file mode 100644 index dc184b8f..00000000 --- a/shared/encryption/rollup.config.js +++ /dev/null @@ -1,65 +0,0 @@ -import terser from "@rollup/plugin-terser"; -import typescript from "@rollup/plugin-typescript"; -import { resolveExtensions } from "@xmtp/rollup-plugin-resolve-extensions"; -import { defineConfig } from "rollup"; -import { dts } from "rollup-plugin-dts"; -import filesize from "rollup-plugin-filesize"; -import tsConfigPaths from "rollup-plugin-tsconfig-paths"; - -const external = ["@xmtp/proto", "node:crypto"]; - -const plugins = [ - tsConfigPaths(), - typescript({ - declaration: false, - declarationMap: false, - }), - filesize({ - showMinifiedSize: false, - }), -]; - -export default defineConfig([ - { - input: "src/index.ts", - output: { - file: "dist/index.js", - format: "es", - sourcemap: true, - }, - plugins, - external, - }, - { - input: "src/index.ts", - output: { - file: "dist/index.cjs", - format: "cjs", - sourcemap: true, - }, - plugins, - external, - }, - { - input: "src/index.ts", - output: { - file: "dist/index.d.ts", - format: "es", - }, - plugins: [tsConfigPaths(), dts()], - }, - { - input: "src/index.ts", - output: { - file: "dist/browser/index.js", - format: "es", - sourcemap: true, - }, - plugins: [ - resolveExtensions({ extensions: [".browser"] }), - terser(), - ...plugins, - ], - external, - }, -]); diff --git a/shared/encryption/test/encryption.test.ts b/shared/encryption/test/encryption.test.ts deleted file mode 100644 index 8f03bf1a..00000000 --- a/shared/encryption/test/encryption.test.ts +++ /dev/null @@ -1,72 +0,0 @@ -import crypto from "@/crypto"; -import { - exportHmacKey, - generateHmacSignature, - hkdfHmacKey, - importHmacKey, - verifyHmacSignature, -} from "@/encryption"; - -describe("HMAC encryption", () => { - it("generates and validates HMAC", async () => { - const secret = crypto.getRandomValues(new Uint8Array(32)); - const info = crypto.getRandomValues(new Uint8Array(32)); - const message = crypto.getRandomValues(new Uint8Array(32)); - const hmac = await generateHmacSignature(secret, info, message); - const key = await hkdfHmacKey(secret, info); - const valid = await verifyHmacSignature(key, hmac, message); - expect(valid).toBe(true); - }); - - it("generates and validates HMAC with imported key", async () => { - const secret = crypto.getRandomValues(new Uint8Array(32)); - const info = crypto.getRandomValues(new Uint8Array(32)); - const message = crypto.getRandomValues(new Uint8Array(32)); - const hmac = await generateHmacSignature(secret, info, message); - const key = await hkdfHmacKey(secret, info); - const exportedKey = await exportHmacKey(key); - const importedKey = await importHmacKey(exportedKey); - const valid = await verifyHmacSignature(importedKey, hmac, message); - expect(valid).toBe(true); - }); - - it("generates different HMAC keys with different infos", async () => { - const secret = crypto.getRandomValues(new Uint8Array(32)); - const info1 = crypto.getRandomValues(new Uint8Array(32)); - const info2 = crypto.getRandomValues(new Uint8Array(32)); - const key1 = await hkdfHmacKey(secret, info1); - const key2 = await hkdfHmacKey(secret, info2); - - expect(await exportHmacKey(key1)).not.toEqual(await exportHmacKey(key2)); - }); - - it("fails to validate HMAC with wrong message", async () => { - const secret = crypto.getRandomValues(new Uint8Array(32)); - const info = crypto.getRandomValues(new Uint8Array(32)); - const message = crypto.getRandomValues(new Uint8Array(32)); - const hmac = await generateHmacSignature(secret, info, message); - const key = await hkdfHmacKey(secret, info); - const valid = await verifyHmacSignature( - key, - hmac, - crypto.getRandomValues(new Uint8Array(32)), - ); - expect(valid).toBe(false); - }); - - it("fails to validate HMAC with wrong key", async () => { - const secret = crypto.getRandomValues(new Uint8Array(32)); - const info = crypto.getRandomValues(new Uint8Array(32)); - const message = crypto.getRandomValues(new Uint8Array(32)); - const hmac = await generateHmacSignature(secret, info, message); - const valid = await verifyHmacSignature( - await hkdfHmacKey( - crypto.getRandomValues(new Uint8Array(32)), - crypto.getRandomValues(new Uint8Array(32)), - ), - hmac, - message, - ); - expect(valid).toBe(false); - }); -}); diff --git a/shared/encryption/tsconfig.json b/shared/encryption/tsconfig.json deleted file mode 100644 index 92aed42a..00000000 --- a/shared/encryption/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "lib": ["dom"], - "moduleResolution": "bundler", - "noEmit": true, - "paths": { - "@/*": ["./src/*"] - }, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "target": "es2021", - "types": ["vitest/globals"] - }, - "include": ["src/**/*", "test/**/*", "rollup.config.js", "vitest.config.ts"] -} diff --git a/shared/encryption/vitest.config.ts b/shared/encryption/vitest.config.ts deleted file mode 100644 index 7f3e1cef..00000000 --- a/shared/encryption/vitest.config.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// -import { defineConfig, mergeConfig } from "vite"; -import tsconfigPaths from "vite-tsconfig-paths"; -import { defineConfig as defineVitestConfig } from "vitest/config"; - -// https://vitejs.dev/config/ -const viteConfig = defineConfig({ - plugins: [tsconfigPaths()], -}); - -const vitestConfig = defineVitestConfig({ - test: { - globals: true, - }, -}); - -export default mergeConfig(viteConfig, vitestConfig); diff --git a/yarn.lock b/yarn.lock index a16d4b0b..f82b15f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1807,24 +1807,6 @@ __metadata: languageName: node linkType: hard -"@rollup/plugin-node-resolve@npm:^15.3.0": - version: 15.3.0 - resolution: "@rollup/plugin-node-resolve@npm:15.3.0" - dependencies: - "@rollup/pluginutils": "npm:^5.0.1" - "@types/resolve": "npm:1.20.2" - deepmerge: "npm:^4.2.2" - is-module: "npm:^1.0.0" - resolve: "npm:^1.22.1" - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: 10/214596dd0ecf0822a135e6cb604f6a4469bac4a9d6b43608d277b47c34762e800b79f5f1c18ea0f7317448165ac0cff2439b35446641e093a5bc5c372940c819 - languageName: node - linkType: hard - "@rollup/plugin-terser@npm:^0.4.4": version: 0.4.4 resolution: "@rollup/plugin-terser@npm:0.4.4" @@ -1860,7 +1842,7 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^5.0.1, @rollup/pluginutils@npm:^5.1.0": +"@rollup/pluginutils@npm:^5.1.0": version: 5.1.2 resolution: "@rollup/pluginutils@npm:5.1.2" dependencies: @@ -2323,13 +2305,6 @@ __metadata: languageName: node linkType: hard -"@types/resolve@npm:1.20.2": - version: 1.20.2 - resolution: "@types/resolve@npm:1.20.2" - checksum: 10/1bff0d3875e7e1557b6c030c465beca9bf3b1173ebc6937cac547654b0af3bb3ff0f16470e9c4d7c5dc308ad9ac8627c38dbff24ef698b66673ff5bd4ead7f7e - languageName: node - linkType: hard - "@types/unist@npm:*, @types/unist@npm:^3.0.0": version: 3.0.3 resolution: "@types/unist@npm:3.0.3" @@ -2656,12 +2631,10 @@ __metadata: resolution: "@xmtp/content-type-remote-attachment@workspace:content-types/content-type-remote-attachment" dependencies: "@noble/secp256k1": "npm:^1.7.1" - "@rollup/plugin-node-resolve": "npm:^15.3.0" "@rollup/plugin-terser": "npm:^0.4.4" "@rollup/plugin-typescript": "npm:^12.1.1" "@types/node": "npm:^20.16.11" "@xmtp/content-type-primitives": "npm:^1.0.2" - "@xmtp/encryption": "workspace:*" "@xmtp/proto": "npm:^3.61.1" "@xmtp/rollup-plugin-resolve-extensions": "npm:^1.0.1" "@xmtp/xmtp-js": "npm:^11.6.3" @@ -2746,29 +2719,6 @@ __metadata: languageName: unknown linkType: soft -"@xmtp/encryption@workspace:*, @xmtp/encryption@workspace:shared/encryption": - version: 0.0.0-use.local - resolution: "@xmtp/encryption@workspace:shared/encryption" - dependencies: - "@rollup/plugin-terser": "npm:^0.4.4" - "@rollup/plugin-typescript": "npm:^12.1.1" - "@types/node": "npm:^20.16.11" - "@vitest/coverage-v8": "npm:^2.1.3" - "@xmtp/proto": "npm:^3.68.0" - "@xmtp/rollup-plugin-resolve-extensions": "npm:1.0.1" - happy-dom: "npm:^15.7.4" - rimraf: "npm:^6.0.1" - rollup: "npm:^4.24.0" - rollup-plugin-dts: "npm:^6.1.1" - rollup-plugin-filesize: "npm:^10.0.0" - rollup-plugin-tsconfig-paths: "npm:^1.5.2" - typescript: "npm:^5.6.3" - vite: "npm:^5.4.9" - vite-tsconfig-paths: "npm:^5.0.1" - vitest: "npm:^2.1.3" - languageName: unknown - linkType: soft - "@xmtp/frames-client@workspace:packages/frames-client": version: 0.0.0-use.local resolution: "@xmtp/frames-client@workspace:packages/frames-client" @@ -2928,7 +2878,6 @@ __metadata: "@metamask/providers": "npm:^17.1.1" "@noble/secp256k1": "npm:1.7.1" "@rollup/plugin-json": "npm:^6.1.0" - "@rollup/plugin-node-resolve": "npm:^15.3.0" "@rollup/plugin-terser": "npm:^0.4.4" "@rollup/plugin-typescript": "npm:^12.1.1" "@types/benchmark": "npm:^2.1.5" @@ -2940,7 +2889,6 @@ __metadata: "@xmtp/consent-proof-signature": "npm:^0.1.3" "@xmtp/content-type-primitives": "npm:^1.0.1" "@xmtp/content-type-text": "npm:^1.0.0" - "@xmtp/encryption": "workspace:*" "@xmtp/proto": "npm:^3.68.0" "@xmtp/rollup-plugin-resolve-extensions": "npm:1.0.1" "@xmtp/user-preferences-bindings-wasm": "npm:^0.3.6" @@ -3753,13 +3701,6 @@ __metadata: languageName: node linkType: hard -"deepmerge@npm:^4.2.2": - version: 4.3.1 - resolution: "deepmerge@npm:4.3.1" - checksum: 10/058d9e1b0ff1a154468bf3837aea436abcfea1ba1d165ddaaf48ca93765fdd01a30d33c36173da8fbbed951dd0a267602bc782fe288b0fc4b7e1e7091afc4529 - languageName: node - linkType: hard - "delegates@npm:^1.0.0": version: 1.0.0 resolution: "delegates@npm:1.0.0" @@ -5053,13 +4994,6 @@ __metadata: languageName: node linkType: hard -"is-module@npm:^1.0.0": - version: 1.0.0 - resolution: "is-module@npm:1.0.0" - checksum: 10/8cd5390730c7976fb4e8546dd0b38865ee6f7bacfa08dfbb2cc07219606755f0b01709d9361e01f13009bbbd8099fa2927a8ed665118a6105d66e40f1b838c3f - languageName: node - linkType: hard - "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0"