diff --git a/apps/web/package-lock.json b/apps/web/package-lock.json index 998c54ca2..1d4ec7cca 100644 --- a/apps/web/package-lock.json +++ b/apps/web/package-lock.json @@ -115,6 +115,7 @@ "happy-dom": "16.0.1", "ip": "^2.0.1", "lorem-ipsum": "^2.0.4", + "openpgp": "^6.2.2", "otplib": "^12.0.1", "rollup-plugin-visualizer": "^5.13.1", "vite": "5.4.11", @@ -507,7 +508,7 @@ }, "../desktop": { "name": "@notesnook/desktop", - "version": "3.3.8-beta.0", + "version": "3.3.8-beta.1", "hasInstallScript": true, "license": "GPL-3.0-or-later", "dependencies": { @@ -9655,6 +9656,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openpgp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-6.2.2.tgz", + "integrity": "sha512-P/dyEqQ3gfwOCo+xsqffzXjmUhGn4AZTOJ1LCcN21S23vAk+EAvMJOQTsb/C8krL6GjOSBxqGYckhik7+hneNw==", + "dev": true, + "license": "LGPL-3.0+", + "engines": { + "node": ">= 18.0.0" + } + }, "node_modules/otplib": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz", diff --git a/apps/web/package.json b/apps/web/package.json index 02961c421..ecc0e3c40 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -113,6 +113,7 @@ "happy-dom": "16.0.1", "ip": "^2.0.1", "lorem-ipsum": "^2.0.4", + "openpgp": "^6.2.2", "otplib": "^12.0.1", "rollup-plugin-visualizer": "^5.13.1", "vite": "5.4.11", diff --git a/apps/web/src/dialogs/inbox-pgp-keys-dialog.tsx b/apps/web/src/dialogs/inbox-pgp-keys-dialog.tsx new file mode 100644 index 000000000..b05a413ac --- /dev/null +++ b/apps/web/src/dialogs/inbox-pgp-keys-dialog.tsx @@ -0,0 +1,210 @@ +/* +This file is part of the Notesnook project (https://notesnook.com/) + +Copyright (C) 2023 Streetwriters (Private) Limited + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +import { useState } from "react"; +import { Button, Flex, Text } from "@theme-ui/components"; +import Dialog from "../components/dialog"; +import { BaseDialogProps, DialogManager } from "../common/dialog-manager"; +import { db } from "../common/db"; +import Field from "../components/field"; +import { showToast } from "../utils/toast"; +import { SerializedKeyPair } from "@notesnook/crypto"; +import { ConfirmDialog } from "./confirm"; + +type InboxPGPKeysDialogProps = BaseDialogProps & { + keys?: SerializedKeyPair | null; +}; + +export const InboxPGPKeysDialog = DialogManager.register( + function InboxPGPKeysDialog(props: InboxPGPKeysDialogProps) { + const { keys: initialKeys, onClose } = props; + const [mode, setMode] = useState<"choose" | "edit">( + initialKeys ? "edit" : "choose" + ); + const [publicKey, setPublicKey] = useState(initialKeys?.publicKey || ""); + const [privateKey, setPrivateKey] = useState(initialKeys?.privateKey || ""); + const [isLoading, setIsLoading] = useState(false); + + const hasChanges = + publicKey !== (initialKeys?.publicKey || "") || + privateKey !== (initialKeys?.privateKey || ""); + + async function handleAutoGenerate() { + try { + setIsLoading(true); + await db.user.getInboxKeys(); + showToast("success", "Inbox keys generated"); + onClose(true); + } catch (error) { + showToast("error", "Failed to generate inbox keys"); + console.error(error); + } finally { + setIsLoading(false); + } + } + + async function handleSave() { + const trimmedPublicKey = publicKey.trim(); + const trimmedPrivateKey = privateKey.trim(); + if (!trimmedPublicKey || !trimmedPrivateKey) { + showToast("error", "Both public and private keys are required"); + return; + } + + try { + setIsLoading(true); + const isValid = await db.storage().validatePGPKeyPair({ + publicKey: trimmedPublicKey, + privateKey: trimmedPrivateKey + }); + if (!isValid) { + showToast( + "error", + "Invalid PGP key pair. Please check your keys and try again." + ); + return; + } + + if (initialKeys) { + const ok = await ConfirmDialog.show({ + title: "Change Inbox PGP Keys", + message: + "Changing Inbox PGP keys will delete all your unsynced inbox items. Are you sure?", + positiveButtonText: "Yes", + negativeButtonText: "No" + }); + if (!ok) return; + } + + await db.user.saveInboxKeys({ + publicKey: trimmedPublicKey, + privateKey: trimmedPrivateKey + }); + showToast("success", "Inbox keys saved"); + onClose(true); + } catch (error) { + showToast("error", "Failed to save inbox keys"); + console.error(error); + } finally { + setIsLoading(false); + } + } + + if (mode === "choose") { + return ( + onClose(false) + }} + > + + + Choose how you want to set up your Inbox PGP keys: + + + + + Or + + + + + + ); + } + + return ( + onClose(false) + }} + > + + setPublicKey(e.target.value)} + sx={{ + fontFamily: "monospace", + fontSize: "body", + minHeight: 150, + resize: "vertical" + }} + placeholder="Enter your PGP public key..." + disabled={isLoading} + /> + setPrivateKey(e.target.value)} + sx={{ + fontFamily: "monospace", + fontSize: "body", + minHeight: 150, + resize: "vertical" + }} + placeholder="Enter your PGP private key..." + disabled={isLoading} + /> + + + ); + } +); diff --git a/apps/web/src/dialogs/settings/inbox-settings.ts b/apps/web/src/dialogs/settings/inbox-settings.ts index 2743972a7..bdec99565 100644 --- a/apps/web/src/dialogs/settings/inbox-settings.ts +++ b/apps/web/src/dialogs/settings/inbox-settings.ts @@ -20,6 +20,10 @@ along with this program. If not, see . import { SettingsGroup } from "./types"; import { useStore as useSettingStore } from "../../stores/setting-store"; import { InboxApiKeys } from "./components/inbox-api-keys"; +import { InboxPGPKeysDialog } from "../inbox-pgp-keys-dialog"; +import { db } from "../../common/db"; +import { showPasswordDialog } from "../password-dialog"; +import { strings } from "@notesnook/intl"; export const InboxSettings: SettingsGroup[] = [ { @@ -42,6 +46,41 @@ export const InboxSettings: SettingsGroup[] = [ } ] }, + { + key: "show-inbox-pgp-keys", + title: "Inbox PGP Keys", + description: "View/edit your Inbox PGP keys", + keywords: ["inbox", "pgp", "keys"], + onStateChange: (listener) => + useSettingStore.subscribe((s) => s.isInboxEnabled, listener), + isHidden: () => !useSettingStore.getState().isInboxEnabled, + components: [ + { + type: "button", + title: "Show", + variant: "secondary", + action: async () => { + const ok = await showPasswordDialog({ + title: "Authenticate to view/edit Inbox PGP keys", + inputs: { + password: { + label: strings.accountPassword(), + autoComplete: "current-password" + } + }, + validate: ({ password }) => { + return db.user.verifyPassword(password); + } + }); + if (!ok) return; + + InboxPGPKeysDialog.show({ + keys: await db.user.getInboxKeys() + }); + } + } + ] + }, { key: "inbox-api-keys", title: "", diff --git a/apps/web/src/interfaces/storage.ts b/apps/web/src/interfaces/storage.ts index 9fb294c6a..a1822e187 100644 --- a/apps/web/src/interfaces/storage.ts +++ b/apps/web/src/interfaces/storage.ts @@ -26,7 +26,6 @@ import { } from "./key-value"; import { NNCrypto } from "./nncrypto"; import type { - AsymmetricCipher, Cipher, SerializedKey, SerializedKeyPair @@ -34,6 +33,7 @@ import type { import { isFeatureSupported } from "../utils/feature-check"; import { IKeyStore } from "./key-store"; import { User } from "@notesnook/core"; +import * as openpgp from "openpgp"; type EncryptedKey = { iv: Uint8Array; cipher: BufferSource }; export type DatabasePersistence = "memory" | "db"; @@ -133,8 +133,44 @@ export class NNStorage implements IStorage { return await NNCrypto.exportKey(password, salt); } - async generateCryptoKeyPair() { - return await NNCrypto.exportKeyPair(); + async generatePGPKeyPair(): Promise { + const keys = await openpgp.generateKey({ + userIDs: [{ name: "NN", email: "NN@NN.NN" }] + }); + return { publicKey: keys.publicKey, privateKey: keys.privateKey }; + } + + async validatePGPKeyPair(keys: SerializedKeyPair): Promise { + try { + const dummyData = JSON.stringify({ + favorite: true, + title: "Hello world" + }); + + const publicKey = await openpgp.readKey({ armoredKey: keys.publicKey }); + const encrypted = await openpgp.encrypt({ + message: await openpgp.createMessage({ + text: dummyData + }), + encryptionKeys: publicKey + }); + + const message = await openpgp.readMessage({ + armoredMessage: encrypted + }); + const privateKey = await openpgp.readPrivateKey({ + armoredKey: keys.privateKey + }); + const decrypted = await openpgp.decrypt({ + message, + decryptionKeys: privateKey + }); + + return decrypted.data === dummyData; + } catch (e) { + console.error("PGP key pair validation error:", e); + return false; + } } async hash(password: string, email: string): Promise { @@ -165,12 +201,21 @@ export class NNStorage implements IStorage { return NNCrypto.decryptMulti(key, items, "text"); } - decryptAsymmetric( - keyPair: SerializedKeyPair, - cipherData: AsymmetricCipher<"base64"> + async decryptPGPMessage( + privateKeyArmored: string, + encryptedMessage: string ): Promise { - cipherData.format = "base64"; - return NNCrypto.decryptAsymmetric(keyPair, cipherData, "base64"); + const message = await openpgp.readMessage({ + armoredMessage: encryptedMessage + }); + const privateKey = await openpgp.readPrivateKey({ + armoredKey: privateKeyArmored + }); + const decrypted = await openpgp.decrypt({ + message, + decryptionKeys: privateKey + }); + return decrypted.data; } /** diff --git a/apps/web/src/stores/setting-store.ts b/apps/web/src/stores/setting-store.ts index f08cc4efb..7ef3b6175 100644 --- a/apps/web/src/stores/setting-store.ts +++ b/apps/web/src/stores/setting-store.ts @@ -27,6 +27,8 @@ import { TimeFormat, DayFormat, WeekFormat } from "@notesnook/core"; import { Profile, TrashCleanupInterval } from "@notesnook/core"; import { showToast } from "../utils/toast"; import { ConfirmDialog } from "../dialogs/confirm"; +import * as openpgp from "openpgp"; +import { InboxPGPKeysDialog } from "../dialogs/inbox-pgp-keys-dialog"; export const HostIds = [ "API_HOST", @@ -294,17 +296,14 @@ class SettingStore extends BaseStore { try { if (isInboxEnabled) { - const inboxTokens = await db.inboxApiKeys.get(); - if (inboxTokens && inboxTokens.length > 0) { - const ok = await ConfirmDialog.show({ - title: "Disable Inbox API", - message: - "Disabling will revoke all existing API keys, they will no longer work. Are you sure?", - positiveButtonText: "Yes", - negativeButtonText: "No" - }); - if (!ok) return; - } + const ok = await ConfirmDialog.show({ + title: "Disable Inbox API", + message: + "Disabling will delete all your unsynced inbox items. Additionally, disabling will revoke all existing API keys, they will no longer work. Are you sure?", + positiveButtonText: "Yes", + negativeButtonText: "No" + }); + if (!ok) return; await db.user.discardInboxKeys(); this.set({ isInboxEnabled: false }); @@ -312,8 +311,10 @@ class SettingStore extends BaseStore { return; } - await db.user.getInboxKeys(); - this.set({ isInboxEnabled: true }); + const ok = await InboxPGPKeysDialog.show({ keys: null }); + if (ok) { + this.set({ isInboxEnabled: true }); + } } catch (e) { if (e instanceof Error) { showToast("error", e.message); diff --git a/packages/core/src/api/sync/merger.ts b/packages/core/src/api/sync/merger.ts index 59a5b6e8f..a35258d18 100644 --- a/packages/core/src/api/sync/merger.ts +++ b/packages/core/src/api/sync/merger.ts @@ -187,24 +187,11 @@ export async function handleInboxItems( continue; } - const decryptedKey = await db.storage().decryptAsymmetric(inboxKeys, { - alg: item.key.alg, - cipher: item.key.cipher, - format: "base64", - length: item.key.length - }); - const decryptedItem = await db.storage().decrypt( - { key: decryptedKey }, - { - alg: item.alg, - iv: item.iv, - cipher: item.cipher, - format: "base64", - length: item.length, - salt: item.salt - } - ); + const decryptedItem = await db + .storage() + .decryptPGPMessage(inboxKeys.privateKey, item.cipher); const parsed = JSON.parse(decryptedItem) as ParsedInboxItem; + if (parsed.type !== "note") { continue; } diff --git a/packages/core/src/api/sync/types.ts b/packages/core/src/api/sync/types.ts index 994fc8451..46fe13f8a 100644 --- a/packages/core/src/api/sync/types.ts +++ b/packages/core/src/api/sync/types.ts @@ -50,8 +50,11 @@ export type SyncTransferItem = { count: number; }; -export type SyncInboxItem = Omit & { - key: Omit, "format" | "salt" | "iv">; +export type SyncInboxItem = { + id: string; + v: number; + cipher: string; + alg: string; }; export type ParsedInboxItem = { diff --git a/packages/core/src/api/user-manager.ts b/packages/core/src/api/user-manager.ts index 53040af2a..dc6ecd513 100644 --- a/packages/core/src/api/user-manager.ts +++ b/packages/core/src/api/user-manager.ts @@ -533,7 +533,7 @@ class UserManager { this.cachedInboxKeys = key; }, userProperty: "inboxKeys", - generateKey: () => this.db.crypto().generateCryptoKeyPair(), + generateKey: () => this.db.crypto().generatePGPKeyPair(), errorContext: "inbox encryption keys", encrypt: async (keys, userEncryptionKey) => { const encryptedPrivateKey = await this.db @@ -584,6 +584,23 @@ class UserManager { await this.setUser({ ...user, inboxKeys: undefined }); } + async saveInboxKeys(keys: SerializedKeyPair) { + this.cachedInboxKeys = keys; + + const userEncryptionKey = await this.getEncryptionKey(); + if (!userEncryptionKey) return; + + const updatePayload = { + inboxKeys: { + public: keys.publicKey, + private: await this.db + .storage() + .encrypt(userEncryptionKey, JSON.stringify(keys.privateKey)) + } + }; + await this.updateUser(updatePayload); + } + async sendVerificationEmail(newEmail?: string) { const token = await this.tokenManager.getAccessToken(); if (!token) return; diff --git a/packages/core/src/interfaces.ts b/packages/core/src/interfaces.ts index eec44365f..59b4a3a77 100644 --- a/packages/core/src/interfaces.ts +++ b/packages/core/src/interfaces.ts @@ -18,7 +18,6 @@ along with this program. If not, see . */ import { - AsymmetricCipher, Cipher, DataFormat, SerializedKey, @@ -63,10 +62,6 @@ export interface IStorage { key: SerializedKey, items: Cipher<"base64">[] ): Promise; - decryptAsymmetric( - keyPair: SerializedKeyPair, - cipherData: AsymmetricCipher<"base64"> - ): Promise; deriveCryptoKey(credentials: SerializedKey): Promise; hash( password: string, @@ -75,7 +70,12 @@ export interface IStorage { ): Promise; getCryptoKey(): Promise; generateCryptoKey(password: string, salt?: string): Promise; - generateCryptoKeyPair(): Promise; + generatePGPKeyPair(): Promise; + decryptPGPMessage( + privateKeyArmored: string, + encryptedMessage: string + ): Promise; + validatePGPKeyPair(keys: SerializedKeyPair): Promise; generateCryptoKeyFallback( password: string, diff --git a/packages/core/src/utils/crypto.ts b/packages/core/src/utils/crypto.ts index b6e65bc4a..0c4b82a63 100644 --- a/packages/core/src/utils/crypto.ts +++ b/packages/core/src/utils/crypto.ts @@ -30,8 +30,8 @@ export class Crypto { return await this.storage().generateCryptoKey(password); } - async generateCryptoKeyPair() { - return await this.storage().generateCryptoKeyPair(); + async generatePGPKeyPair() { + return await this.storage().generatePGPKeyPair(); } } diff --git a/packages/crypto/src/decryption.ts b/packages/crypto/src/decryption.ts index ee55d38cc..b3cec4115 100644 --- a/packages/crypto/src/decryption.ts +++ b/packages/crypto/src/decryption.ts @@ -19,19 +19,12 @@ along with this program. If not, see . import { ISodium } from "@notesnook/sodium"; import KeyUtils, { base64_variants } from "./keyutils.js"; -import { - Cipher, - Output, - DataFormat, - SerializedKey, - SerializedKeyPair, - AsymmetricCipher -} from "./types.js"; +import { Cipher, Output, DataFormat, SerializedKey } from "./types.js"; export default class Decryption { private static transformInput( sodium: ISodium, - cipherData: Cipher | AsymmetricCipher + cipherData: Cipher ): Uint8Array { let input: Uint8Array | null = null; if ( @@ -80,28 +73,6 @@ export default class Decryption { ) as Output; } - static decryptAsymmetric( - sodium: ISodium, - keyPair: SerializedKeyPair, - cipherData: AsymmetricCipher, - outputFormat: TOutputFormat = "text" as TOutputFormat - ): Output { - const input = this.transformInput(sodium, cipherData); - const plaintext = sodium.crypto_box_seal_open( - input, - sodium.from_base64(keyPair.publicKey), - sodium.from_base64(keyPair.privateKey) - ); - - return ( - outputFormat === "base64" - ? sodium.to_base64(plaintext, base64_variants.URLSAFE_NO_PADDING) - : outputFormat === "text" - ? sodium.to_string(plaintext) - : plaintext - ) as Output; - } - static createStream( sodium: ISodium, header: string, diff --git a/packages/crypto/src/index.ts b/packages/crypto/src/index.ts index 4af8962f7..b41d7fec8 100644 --- a/packages/crypto/src/index.ts +++ b/packages/crypto/src/index.ts @@ -31,8 +31,7 @@ import { DataFormat, SerializedKey, SerializedKeyPair, - EncryptionKeyPair, - AsymmetricCipher + EncryptionKeyPair } from "./types.js"; export class NNCrypto implements INNCrypto { @@ -98,20 +97,6 @@ export class NNCrypto implements INNCrypto { return decryptedItems; } - async decryptAsymmetric( - keyPair: SerializedKeyPair, - cipherData: AsymmetricCipher, - outputFormat: TOutputFormat = "text" as TOutputFormat - ): Promise> { - await this.init(); - return Decryption.decryptAsymmetric( - this.sodium, - keyPair, - cipherData, - outputFormat - ); - } - async hash(password: string, salt: string): Promise { await this.init(); return Password.hash(this.sodium, password, salt); diff --git a/packages/crypto/src/interfaces.ts b/packages/crypto/src/interfaces.ts index 67520ac85..a508a8a7d 100644 --- a/packages/crypto/src/interfaces.ts +++ b/packages/crypto/src/interfaces.ts @@ -26,8 +26,7 @@ import { Output, Input, EncryptionKeyPair, - SerializedKeyPair, - AsymmetricCipher + SerializedKeyPair } from "./types.js"; export interface IStreamable { @@ -62,12 +61,6 @@ export interface INNCrypto { outputFormat?: TOutputFormat ): Promise[]>; - decryptAsymmetric( - keyPair: SerializedKeyPair, - cipherData: AsymmetricCipher, - outputFormat?: TOutputFormat - ): Promise>; - hash(password: string, salt: string): Promise; deriveKey(password: string, salt?: string): Promise; diff --git a/packages/crypto/src/types.ts b/packages/crypto/src/types.ts index c29b9bbbc..1fda92cd7 100644 --- a/packages/crypto/src/types.ts +++ b/packages/crypto/src/types.ts @@ -30,11 +30,6 @@ export type Cipher = { length: number; }; -export type AsymmetricCipher = Omit< - Cipher, - "iv" | "salt" ->; - export type Output = TFormat extends StringOutputFormat ? string : Uint8Array; export type Input = Output; diff --git a/packages/sodium/src/browser.ts b/packages/sodium/src/browser.ts index cc9c71892..5a2528320 100644 --- a/packages/sodium/src/browser.ts +++ b/packages/sodium/src/browser.ts @@ -118,12 +118,6 @@ export class Sodium implements ISodium { get crypto_secretstream_xchacha20poly1305_TAG_MESSAGE() { return sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE; } - get crypto_box_keypair() { - return sodium.crypto_box_keypair; - } - get crypto_box_seal_open() { - return sodium.crypto_box_seal_open; - } } function convertVariant(variant: base64_variants): sodium.base64_variants { diff --git a/packages/sodium/src/node.ts b/packages/sodium/src/node.ts index b7c1cd923..3164bf4ed 100644 --- a/packages/sodium/src/node.ts +++ b/packages/sodium/src/node.ts @@ -46,12 +46,7 @@ import { crypto_aead_xchacha20poly1305_ietf_KEYBYTES, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, crypto_secretstream_xchacha20poly1305_TAG_FINAL, - crypto_secretstream_xchacha20poly1305_TAG_MESSAGE, - crypto_box_keypair as sodium_native_crypto_box_keypair, - crypto_box_PUBLICKEYBYTES, - crypto_box_SECRETKEYBYTES, - crypto_box_seal_open as sodium_native_crypto_box_seal_open, - crypto_box_SEALBYTES + crypto_secretstream_xchacha20poly1305_TAG_MESSAGE } from "sodium-native"; import { Buffer } from "node:buffer"; import { base64_variants, ISodium } from "./types"; @@ -346,71 +341,6 @@ function crypto_secretstream_xchacha20poly1305_pull( return { message, tag: tag.readUInt8() } as MessageTag | StringMessageTag; } -function crypto_box_keypair( - outputFormat?: Uint8ArrayOutputFormat | null -): KeyPair; -function crypto_box_keypair(outputFormat: StringOutputFormat): StringKeyPair; -function crypto_box_keypair( - outputFormat?: Uint8ArrayOutputFormat | null | StringOutputFormat -): KeyPair | StringKeyPair { - const publicBuffer = Buffer.alloc(crypto_box_PUBLICKEYBYTES); - const privateBuffer = Buffer.alloc(crypto_box_SECRETKEYBYTES); - - sodium_native_crypto_box_keypair(publicBuffer, privateBuffer); - - if (typeof outputFormat === "string") { - const transformer = - outputFormat === "base64" - ? to_base64 - : outputFormat === "hex" - ? to_hex - : to_string; - return { - keyType: "x25519" as KeyType, - publicKey: transformer(new Uint8Array(publicBuffer)), - privateKey: transformer(new Uint8Array(privateBuffer)) - }; - } else { - return { - keyType: "x25519" as KeyType, - publicKey: new Uint8Array(publicBuffer), - privateKey: new Uint8Array(privateBuffer) - }; - } -} - -function crypto_box_seal_open( - ciphertext: string | Uint8Array, - publicKey: Uint8Array, - privateKey: Uint8Array, - outputFormat?: Uint8ArrayOutputFormat | null -): Uint8Array; -function crypto_box_seal_open( - ciphertext: string | Uint8Array, - publicKey: Uint8Array, - privateKey: Uint8Array, - outputFormat: StringOutputFormat -): string; -function crypto_box_seal_open( - ciphertext: string | Uint8Array, - publicKey: Uint8Array, - privateKey: Uint8Array, - outputFormat?: StringOutputFormat | Uint8ArrayOutputFormat | null -): string | Uint8Array { - const cipher = toBuffer(ciphertext); - return wrap( - cipher.byteLength - crypto_box_SEALBYTES, - (message) => - sodium_native_crypto_box_seal_open( - message, - cipher, - toBuffer(publicKey), - toBuffer(privateKey) - ), - outputFormat - ); -} - function randombytes_buf( length: number, outputFormat?: Uint8ArrayOutputFormat | null @@ -473,10 +403,6 @@ function to_string(input: Uint8Array): string { ); } -function to_hex(input: Uint8Array): string { - return Buffer.from(input, input.byteOffset, input.byteLength).toString("hex"); -} - type ToBufferInput = string | Uint8Array | null | undefined; type ToBufferResult = TInput extends | undefined @@ -625,12 +551,6 @@ export class Sodium implements ISodium { get crypto_secretstream_xchacha20poly1305_TAG_MESSAGE() { return crypto_secretstream_xchacha20poly1305_TAG_MESSAGE; } - get crypto_box_keypair() { - return crypto_box_keypair; - } - get crypto_box_seal_open() { - return crypto_box_seal_open; - } } export { base64_variants, type ISodium }; diff --git a/packages/sodium/src/types.ts b/packages/sodium/src/types.ts index 36d3d5700..2a68bf9e6 100644 --- a/packages/sodium/src/types.ts +++ b/packages/sodium/src/types.ts @@ -61,6 +61,4 @@ export interface ISodium { get crypto_aead_xchacha20poly1305_ietf_NPUBBYTES(): typeof sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES; get crypto_secretstream_xchacha20poly1305_TAG_FINAL(): typeof sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL; get crypto_secretstream_xchacha20poly1305_TAG_MESSAGE(): typeof sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE; - get crypto_box_keypair(): typeof sodium.crypto_box_keypair; - get crypto_box_seal_open(): typeof sodium.crypto_box_seal_open; }