From ef51ba983f49b32a04bb8460f24f720f7952f306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20=C3=81valos?= Date: Fri, 30 Jun 2023 17:52:24 -0600 Subject: WIP: initial work for Anastasis in qtart --- packages/anastasis-core/package.json | 1 - packages/anastasis-core/src/crypto.ts | 34 ++++++++++------------- packages/taler-util/package.json | 5 ++-- packages/taler-util/src/taler-crypto.ts | 35 ++++++++++++++++++++++++ packages/taler-wallet-embedded/package.json | 3 +- packages/taler-wallet-embedded/src/wallet-qjs.ts | 31 ++++++++++++++++++++- pnpm-lock.yaml | 11 +++++--- 7 files changed, 92 insertions(+), 28 deletions(-) diff --git a/packages/anastasis-core/package.json b/packages/anastasis-core/package.json index d45d28129..c3a7106fb 100644 --- a/packages/anastasis-core/package.json +++ b/packages/anastasis-core/package.json @@ -23,7 +23,6 @@ "dependencies": { "@gnu-taler/taler-util": "workspace:*", "fflate": "^0.7.4", - "hash-wasm": "^4.9.0", "tslib": "^2.5.3" }, "ava": { diff --git a/packages/anastasis-core/src/crypto.ts b/packages/anastasis-core/src/crypto.ts index 5e45f995f..3a9483aa1 100644 --- a/packages/anastasis-core/src/crypto.ts +++ b/packages/anastasis-core/src/crypto.ts @@ -26,8 +26,8 @@ import { secretbox_open, hash, bytesToString, + hashArgon2id, } from "@gnu-taler/taler-util"; -import { argon2id } from "hash-wasm"; export type Flavor = T & { _flavor?: `anastasis.${FlavorT}`; @@ -71,15 +71,13 @@ export async function userIdentifierDerive( ): Promise { const canonIdData = canonicalJson(idData); const hashInput = stringToBytes(canonIdData); - const result = await argon2id({ - hashLength: 64, - iterations: 3, - memorySize: 1024 /* kibibytes */, - parallelism: 1, - password: hashInput, - salt: decodeCrock(serverSalt), - outputType: "binary", - }); + const result = await hashArgon2id( + hashInput, // password + decodeCrock(serverSalt), // salt + 3, // iterations + 1024, // memoryLimit (kibibytes) + 64, // hashLength + ); return encodeCrock(result); } @@ -343,15 +341,13 @@ export async function secureAnswerHash( truthUuid: TruthUuid, questionSalt: TruthSalt, ): Promise { - const powResult = await argon2id({ - hashLength: 64, - iterations: 3, - memorySize: 1024 /* kibibytes */, - parallelism: 1, - password: stringToBytes(answer), - salt: decodeCrock(questionSalt), - outputType: "binary", - }); + const powResult = await hashArgon2id( + stringToBytes(answer), // password + decodeCrock(questionSalt), // salt + 3, // iterations + 1024, // memorySize (kibibytes) + 64, // hashLength + ); const kdfResult = kdfKw({ outputLength: 64, salt: decodeCrock(truthUuid), diff --git a/packages/taler-util/package.json b/packages/taler-util/package.json index 40fa94923..766163c48 100644 --- a/packages/taler-util/package.json +++ b/packages/taler-util/package.json @@ -69,11 +69,12 @@ "big-integer": "^1.6.51", "fflate": "^0.7.4", "jed": "^1.1.1", - "tslib": "^2.5.3" + "tslib": "^2.5.3", + "hash-wasm": "^4.9.0" }, "ava": { "files": [ "lib/**/*test.js" ] } -} \ No newline at end of file +} diff --git a/packages/taler-util/src/taler-crypto.ts b/packages/taler-util/src/taler-crypto.ts index e3f7d49a8..cabe2b7d0 100644 --- a/packages/taler-util/src/taler-crypto.ts +++ b/packages/taler-util/src/taler-crypto.ts @@ -24,6 +24,7 @@ import * as nacl from "./nacl-fast.js"; import { hmacSha256, hmacSha512 } from "./kdf.js"; import bigint from "big-integer"; +import { argon2id } from "hash-wasm"; import { CoinEnvelope, CoinPublicKeyString, @@ -69,6 +70,13 @@ interface NativeTartLib { encodeCrock(buf: Uint8Array | ArrayBuffer): string; decodeCrock(str: string): Uint8Array; hash(buf: Uint8Array): Uint8Array; + hashArgon2id( + password: Uint8Array, + salt: Uint8Array, + iterations: number, + memorySize: number, + hashLength: number, + ): Uint8Array; eddsaGetPublic(buf: Uint8Array): Uint8Array; ecdheGetPublic(buf: Uint8Array): Uint8Array; eddsaSign(msg: Uint8Array, priv: Uint8Array): Uint8Array; @@ -253,6 +261,33 @@ export function decodeCrock(encoded: string): Uint8Array { return out; } +export async function hashArgon2id( + password: Uint8Array, + salt: Uint8Array, + iterations: number, + memorySize: number, + hashLength: number, +): Promise { + if (tart) { + return tart.hashArgon2id( + password, + salt, + iterations, + memorySize, + hashLength, + ); + } + return await argon2id({ + password: password, + salt: salt, + iterations: iterations, + memorySize: memorySize, + hashLength: hashLength, + parallelism: 1, + outputType: "binary", + }); +} + export function eddsaGetPublic(eddsaPriv: Uint8Array): Uint8Array { if (tart) { return tart.eddsaGetPublic(eddsaPriv); diff --git a/packages/taler-wallet-embedded/package.json b/packages/taler-wallet-embedded/package.json index 74616c69b..b96edff25 100644 --- a/packages/taler-wallet-embedded/package.json +++ b/packages/taler-wallet-embedded/package.json @@ -36,6 +36,7 @@ "@gnu-taler/idb-bridge": "workspace:*", "@gnu-taler/taler-util": "workspace:*", "@gnu-taler/taler-wallet-core": "workspace:*", + "@gnu-taler/anastasis-core": "workspace:*", "tslib": "^2.5.3" } -} \ No newline at end of file +} diff --git a/packages/taler-wallet-embedded/src/wallet-qjs.ts b/packages/taler-wallet-embedded/src/wallet-qjs.ts index 2b1c8a108..db0aeacb6 100644 --- a/packages/taler-wallet-embedded/src/wallet-qjs.ts +++ b/packages/taler-wallet-embedded/src/wallet-qjs.ts @@ -41,6 +41,10 @@ import { Wallet, WalletApiOperation, } from "@gnu-taler/taler-wallet-core"; +import { + reduceAction, + ReducerState, +} from "@gnu-taler/anastasis-core"; setGlobalLogLevelFromString("trace"); @@ -169,6 +173,25 @@ class NativeWalletMessageHandler { } } +/** + * Handle an Anastasis request from the native app. + */ +async function handleAnastasisRequest( + state: ReducerState, + action: string, + id: string, + args: any, +): Promise { + // For now, this will return "success" even if the wrapped Anastasis + // response is a ReducerStateError. + return { + type: "response", + id, + operation: "anastasis", + result: await reduceAction(state, action, args), + }; +} + export function installNativeWalletListener(): void { setGlobalLogLevelFromString("trace"); const handler = new NativeWalletMessageHandler(); @@ -190,7 +213,13 @@ export function installNativeWalletListener(): void { let respMsg: CoreApiResponse; try { - respMsg = await handler.handleMessage(operation, id, msg.args ?? {}); + if (msg.operation === "anastasis") { + // TODO: do some input validation here + let req = msg.args ?? {}; + respMsg = await handleAnastasisRequest(req.state, req.action, id, req.args ?? {}); + } else { + respMsg = await handler.handleMessage(operation, id, msg.args ?? {}); + } } catch (e) { respMsg = { type: "error", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d40b0290..45b11cf08 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: '6.1' +lockfileVersion: '6.0' settings: autoInstallPeers: true @@ -120,9 +120,6 @@ importers: fflate: specifier: ^0.7.4 version: 0.7.4 - hash-wasm: - specifier: ^4.9.0 - version: 4.9.0 tslib: specifier: ^2.5.3 version: 2.5.3 @@ -581,6 +578,9 @@ importers: fflate: specifier: ^0.7.4 version: 0.7.4 + hash-wasm: + specifier: ^4.9.0 + version: 4.9.0 jed: specifier: ^1.1.1 version: 1.1.1 @@ -716,6 +716,9 @@ importers: packages/taler-wallet-embedded: dependencies: + '@gnu-taler/anastasis-core': + specifier: workspace:* + version: link:../anastasis-core '@gnu-taler/idb-bridge': specifier: workspace:* version: link:../idb-bridge -- cgit v1.2.3