aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/synchronousWorkerNode.ts204
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/synchronousWorkerWeb.ts127
-rw-r--r--packages/taler-wallet-core/src/index.browser.ts1
-rw-r--r--packages/taler-wallet-core/src/index.node.ts1
-rw-r--r--packages/taler-wallet-core/src/index.ts1
5 files changed, 333 insertions, 1 deletions
diff --git a/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerNode.ts b/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerNode.ts
new file mode 100644
index 000000000..c1620574f
--- /dev/null
+++ b/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerNode.ts
@@ -0,0 +1,204 @@
+/*
+ This file is part of GNU Taler
+ (C) 2019 GNUnet e.V.
+
+ GNU Taler 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, or (at your option) any later version.
+
+ GNU Taler 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
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { Logger } from "@gnu-taler/taler-util";
+import {
+ nativeCryptoR,
+ TalerCryptoInterfaceR,
+} from "../cryptoImplementation.js";
+import { CryptoRpcClient } from "./rpcClient.js";
+
+const logger = new Logger("synchronousWorker.ts");
+
+/**
+ * Worker implementation that uses node subprocesses.
+ */
+export class SynchronousCryptoWorker {
+ /**
+ * Function to be called when we receive a message from the worker thread.
+ */
+ onmessage: undefined | ((m: any) => void);
+
+ /**
+ * Function to be called when we receive an error from the worker thread.
+ */
+ onerror: undefined | ((m: any) => void);
+
+ cryptoImplR: TalerCryptoInterfaceR;
+
+ rpcClient: CryptoRpcClient | undefined;
+
+ constructor() {
+ this.onerror = undefined;
+ this.onmessage = undefined;
+
+ this.cryptoImplR = { ...nativeCryptoR };
+
+ if (process.env["TALER_WALLET_PRIMITIVE_WORKER"]) {
+ logger.info("using RPC for some crypto operations");
+ const rpc = (this.rpcClient = new CryptoRpcClient());
+ this.cryptoImplR.eddsaSign = async (_, req) => {
+ return await rpc.queueRequest({
+ op: "eddsa_sign",
+ args: {
+ msg: req.msg,
+ priv: req.priv,
+ },
+ });
+ };
+ this.cryptoImplR.setupRefreshPlanchet = async (_, req) => {
+ const res = await rpc.queueRequest({
+ op: "setup_refresh_planchet",
+ args: {
+ coin_index: req.coinNumber,
+ transfer_secret: req.transferSecret,
+ },
+ });
+ return {
+ bks: res.blinding_key,
+ coinPriv: res.coin_priv,
+ coinPub: res.coin_pub,
+ };
+ };
+ this.cryptoImplR.rsaBlind = async (_, req) => {
+ const res = await rpc.queueRequest({
+ op: "rsa_blind",
+ args: {
+ bks: req.bks,
+ hm: req.hm,
+ pub: req.pub,
+ },
+ });
+ return {
+ blinded: res.blinded,
+ };
+ };
+ this.cryptoImplR.keyExchangeEcdheEddsa = async (_, req) => {
+ const res = await rpc.queueRequest({
+ op: "kx_ecdhe_eddsa",
+ args: {
+ ecdhe_priv: req.ecdhePriv,
+ eddsa_pub: req.eddsaPub,
+ },
+ });
+ return {
+ h: res.h,
+ };
+ };
+ this.cryptoImplR.eddsaGetPublic = async (_, req) => {
+ const res = await rpc.queueRequest({
+ op: "eddsa_get_public",
+ args: {
+ eddsa_priv: req.priv,
+ },
+ });
+ return {
+ pub: res.eddsa_pub,
+ };
+ };
+ this.cryptoImplR.ecdheGetPublic = async (_, req) => {
+ const res = await rpc.queueRequest({
+ op: "ecdhe_get_public",
+ args: {
+ ecdhe_priv: req.priv,
+ },
+ });
+ return {
+ pub: res.ecdhe_pub,
+ };
+ };
+ }
+ }
+
+ /**
+ * Add an event listener for either an "error" or "message" event.
+ */
+ addEventListener(event: "message" | "error", fn: (x: any) => void): void {
+ switch (event) {
+ case "message":
+ this.onmessage = fn;
+ break;
+ case "error":
+ this.onerror = fn;
+ break;
+ }
+ }
+
+ private dispatchMessage(msg: any): void {
+ if (this.onmessage) {
+ this.onmessage({ data: msg });
+ }
+ }
+
+ private async handleRequest(
+ operation: string,
+ id: number,
+ req: unknown,
+ ): Promise<void> {
+ const impl = this.cryptoImplR;
+
+ if (!(operation in impl)) {
+ console.error(`crypto operation '${operation}' not found`);
+ return;
+ }
+
+ let result: any;
+ try {
+ result = await (impl as any)[operation](impl, req);
+ } catch (e: any) {
+ logger.error(`error during operation '${operation}': ${e}`);
+ return;
+ }
+
+ try {
+ setTimeout(() => this.dispatchMessage({ result, id }), 0);
+ } catch (e) {
+ logger.error("got error during dispatch", e);
+ }
+ }
+
+ /**
+ * Send a message to the worker thread.
+ */
+ postMessage(msg: any): void {
+ const args = msg.args;
+ if (!Array.isArray(args)) {
+ console.error("args must be array");
+ return;
+ }
+ const id = msg.id;
+ if (typeof id !== "number") {
+ console.error("RPC id must be number");
+ return;
+ }
+ const operation = msg.operation;
+ if (typeof operation !== "string") {
+ console.error("RPC operation must be string");
+ return;
+ }
+
+ this.handleRequest(operation, id, args).catch((e) => {
+ console.error("Error while handling crypto request:", e);
+ });
+ }
+
+ /**
+ * Forcibly terminate the worker thread.
+ */
+ terminate(): void {
+ // This is a no-op.
+ }
+}
diff --git a/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerWeb.ts b/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerWeb.ts
new file mode 100644
index 000000000..3a2bddeed
--- /dev/null
+++ b/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerWeb.ts
@@ -0,0 +1,127 @@
+/*
+ This file is part of GNU Taler
+ (C) 2019 GNUnet e.V.
+
+ GNU Taler 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, or (at your option) any later version.
+
+ GNU Taler 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
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { Logger } from "@gnu-taler/taler-util";
+import {
+ nativeCryptoR,
+ TalerCryptoInterfaceR,
+} from "../cryptoImplementation.js";
+
+
+
+const logger = new Logger("synchronousWorker.ts");
+
+/**
+ * Worker implementation that uses node subprocesses.
+ */
+export class SynchronousCryptoWorker {
+ /**
+ * Function to be called when we receive a message from the worker thread.
+ */
+ onmessage: undefined | ((m: any) => void);
+
+ /**
+ * Function to be called when we receive an error from the worker thread.
+ */
+ onerror: undefined | ((m: any) => void);
+
+ cryptoImplR: TalerCryptoInterfaceR;
+
+ constructor() {
+ this.onerror = undefined;
+ this.onmessage = undefined;
+ this.cryptoImplR = { ...nativeCryptoR };
+ }
+
+ /**
+ * Add an event listener for either an "error" or "message" event.
+ */
+ addEventListener(event: "message" | "error", fn: (x: any) => void): void {
+ switch (event) {
+ case "message":
+ this.onmessage = fn;
+ break;
+ case "error":
+ this.onerror = fn;
+ break;
+ }
+ }
+
+ private dispatchMessage(msg: any): void {
+ if (this.onmessage) {
+ this.onmessage({ data: msg });
+ }
+ }
+
+ private async handleRequest(
+ operation: string,
+ id: number,
+ args: string[],
+ ): Promise<void> {
+ const impl = this.cryptoImplR;
+
+ if (!(operation in impl)) {
+ console.error(`crypto operation '${operation}' not found`);
+ return;
+ }
+
+ let result: any;
+ try {
+ result = await (impl as any)[operation](...args);
+ } catch (e: any) {
+ logger.error(`error during operation '${operation}': ${e}`);
+ return;
+ }
+
+ try {
+ setTimeout(() => this.dispatchMessage({ result, id }), 0);
+ } catch (e) {
+ logger.error("got error during dispatch", e);
+ }
+ }
+
+ /**
+ * Send a message to the worker thread.
+ */
+ postMessage(msg: any): void {
+ const args = msg.args;
+ if (!Array.isArray(args)) {
+ console.error("args must be array");
+ return;
+ }
+ const id = msg.id;
+ if (typeof id !== "number") {
+ console.error("RPC id must be number");
+ return;
+ }
+ const operation = msg.operation;
+ if (typeof operation !== "string") {
+ console.error("RPC operation must be string");
+ return;
+ }
+
+ this.handleRequest(operation, id, args).catch((e) => {
+ console.error("Error while handling crypto request:", e);
+ });
+ }
+
+ /**
+ * Forcibly terminate the worker thread.
+ */
+ terminate(): void {
+ // This is a no-op.
+ }
+}
diff --git a/packages/taler-wallet-core/src/index.browser.ts b/packages/taler-wallet-core/src/index.browser.ts
index 88ea52479..029bc533f 100644
--- a/packages/taler-wallet-core/src/index.browser.ts
+++ b/packages/taler-wallet-core/src/index.browser.ts
@@ -15,3 +15,4 @@
*/
export * from "./index.js";
+export { SynchronousCryptoWorker } from "./crypto/workers/synchronousWorkerWeb.js";
diff --git a/packages/taler-wallet-core/src/index.node.ts b/packages/taler-wallet-core/src/index.node.ts
index 33d9c4a27..d7211b4dc 100644
--- a/packages/taler-wallet-core/src/index.node.ts
+++ b/packages/taler-wallet-core/src/index.node.ts
@@ -24,6 +24,7 @@ export {
DefaultNodeWalletArgs,
} from "./headless/helpers.js";
export * from "./crypto/workers/nodeThreadWorker.js";
+export { SynchronousCryptoWorker } from "./crypto/workers/synchronousWorkerNode.js";
export type { AccessStats } from "@gnu-taler/idb-bridge";
export * from "./crypto/workers/synchronousWorkerFactory.js";
diff --git a/packages/taler-wallet-core/src/index.ts b/packages/taler-wallet-core/src/index.ts
index 979d631c0..6b97f56f4 100644
--- a/packages/taler-wallet-core/src/index.ts
+++ b/packages/taler-wallet-core/src/index.ts
@@ -38,7 +38,6 @@ export {
CryptoWorkerFactory,
CryptoDispatcher,
} from "./crypto/workers/cryptoDispatcher.js";
-export { SynchronousCryptoWorker } from "./crypto/workers/synchronousWorker.js";
export * from "./pending-types.js";