From a7b89247e41c272027d9c90a13c9a76901019daa Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 5 Jan 2022 20:29:55 +0100 Subject: [PATCH] wallet-core: towards exchange protocol v12 --- packages/taler-util/src/talerTypes.ts | 6 +++ packages/taler-wallet-cli/rollup.config.js | 15 +++++-- .../src/crypto/cryptoTypes.ts | 3 +- .../crypto/workers/cryptoImplementation.ts | 37 +++++++++++----- .../src/operations/refresh.ts | 44 ++++++++++++++++--- packages/taler-wallet-core/src/versions.ts | 2 +- 6 files changed, 86 insertions(+), 21 deletions(-) diff --git a/packages/taler-util/src/talerTypes.ts b/packages/taler-util/src/talerTypes.ts index 15dc88ca5..e7d8a8c18 100644 --- a/packages/taler-util/src/talerTypes.ts +++ b/packages/taler-util/src/talerTypes.ts @@ -1620,3 +1620,9 @@ export const codecForMerchantConfigResponse = (): Codec .property("name", codecForString()) .property("version", codecForString()) .build("MerchantConfigResponse"); + + +export enum ExchangeProtocolVersion { + V9 = 9, + V12 = 12, +} diff --git a/packages/taler-wallet-cli/rollup.config.js b/packages/taler-wallet-cli/rollup.config.js index 6f877ea27..15ec58e5e 100644 --- a/packages/taler-wallet-cli/rollup.config.js +++ b/packages/taler-wallet-cli/rollup.config.js @@ -4,7 +4,8 @@ import nodeResolve from "@rollup/plugin-node-resolve"; import json from "@rollup/plugin-json"; import builtins from "builtin-modules"; import pkg from "./package.json"; -import sourcemaps from 'rollup-plugin-sourcemaps'; +import sourcemaps from "rollup-plugin-sourcemaps"; +import path from "path"; export default { input: "lib/index.js", @@ -12,6 +13,15 @@ export default { file: pkg.main, format: "cjs", sourcemap: true, + sourcemapPathTransform: (relativeSourcePath, sourcemapPath) => { + // Transform to source map paths to virtual path. Otherwise, + // error messages would contain paths that look like they should exist (relative to + // the bundle) but don't. + const res = path.normalize( + path.join("/_walletsrc/packages/taler-wallet-cli/src/", relativeSourcePath), + ); + return res; + }, }, external: builtins, plugins: [ @@ -29,5 +39,4 @@ export default { json(), ], -} - +}; diff --git a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts index 7d616ecb6..9b72dfbe2 100644 --- a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts +++ b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts @@ -27,7 +27,7 @@ /** * Imports. */ -import { AmountJson, DenominationPubKey } from "@gnu-taler/taler-util"; +import { AmountJson, DenominationPubKey, ExchangeProtocolVersion } from "@gnu-taler/taler-util"; export interface RefreshNewDenomInfo { count: number; @@ -41,6 +41,7 @@ export interface RefreshNewDenomInfo { * secret seed. */ export interface DeriveRefreshSessionRequest { + exchangeProtocolVersion: ExchangeProtocolVersion; sessionSecretSeed: string; kappa: number; meltCoinPub: string; diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts index b5987582a..9e2dc18f3 100644 --- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts @@ -36,6 +36,7 @@ import { buildSigPS, CoinDepositPermission, DenomKeyType, + ExchangeProtocolVersion, FreshCoin, hashDenomPub, RecoupRequest, @@ -162,7 +163,7 @@ async function myEddsaSign( export class CryptoImplementation { static enableTracing = false; - constructor(private primitiveWorker?: PrimitiveWorker) { } + constructor(private primitiveWorker?: PrimitiveWorker) {} /** * Create a pre-coin of the given denomination to be withdrawn from then given @@ -364,18 +365,18 @@ export class CryptoImplementation { } isValidWireAccount( - versionCurrent: number, + versionCurrent: ExchangeProtocolVersion, paytoUri: string, sig: string, masterPub: string, ): boolean { - if (versionCurrent === 10 || versionCurrent === 11) { + if (versionCurrent === ExchangeProtocolVersion.V12) { const paytoHash = hash(stringToBytes(paytoUri + "\0")); const p = buildSigPS(TalerSignaturePurpose.MASTER_WIRE_DETAILS) .put(paytoHash) .build(); return eddsaVerify(p, decodeCrock(sig), decodeCrock(masterPub)); - } else if (versionCurrent === 9) { + } else if (versionCurrent === ExchangeProtocolVersion.V9) { const h = kdf( 64, stringToBytes("exchange-wire-signature"), @@ -623,13 +624,27 @@ export class CryptoImplementation { } const sessionHash = sessionHc.finish(); - const confirmData = buildSigPS(TalerSignaturePurpose.WALLET_COIN_MELT) - .put(sessionHash) - .put(decodeCrock(meltCoinDenomPubHash)) - .put(amountToBuffer(valueWithFee)) - .put(amountToBuffer(meltFee)) - .put(decodeCrock(meltCoinPub)) - .build(); + let confirmData: Uint8Array; + if (req.exchangeProtocolVersion === ExchangeProtocolVersion.V9) { + confirmData = buildSigPS(TalerSignaturePurpose.WALLET_COIN_MELT) + .put(sessionHash) + .put(decodeCrock(meltCoinDenomPubHash)) + .put(amountToBuffer(valueWithFee)) + .put(amountToBuffer(meltFee)) + .put(decodeCrock(meltCoinPub)) + .build(); + } else if (req.exchangeProtocolVersion === ExchangeProtocolVersion.V12) { + confirmData = buildSigPS(TalerSignaturePurpose.WALLET_COIN_MELT) + .put(sessionHash) + .put(decodeCrock(meltCoinDenomPubHash)) + .put(amountToBuffer(valueWithFee)) + .put(amountToBuffer(meltFee)) + .build(); + } else { + throw Error( + `Exchange protocol version (${req.exchangeProtocolVersion}) not supported`, + ); + } const confirmSigResp = await myEddsaSign(this.primitiveWorker, { msg: encodeCrock(confirmData), diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index 51eac4a64..00eaa0eac 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -17,6 +17,7 @@ import { DenomKeyType, encodeCrock, + ExchangeProtocolVersion, getRandomBytes, HttpStatusCode, } from "@gnu-taler/taler-util"; @@ -91,8 +92,10 @@ export function getTotalRefreshCost( refreshedDenom: DenominationRecord, amountLeft: AmountJson, ): AmountJson { - const withdrawAmount = Amounts.sub(amountLeft, refreshedDenom.feeRefresh) - .amount; + const withdrawAmount = Amounts.sub( + amountLeft, + refreshedDenom.feeRefresh, + ).amount; const withdrawDenoms = selectWithdrawalDenominations(withdrawAmount, denoms); const resultingAmount = Amounts.add( Amounts.getZero(withdrawAmount.currency), @@ -198,9 +201,10 @@ async function refreshCreateSession( } // FIXME: use an index here, based on the withdrawal expiration time. - const availableDenoms: DenominationRecord[] = await tx.denominations.indexes.byExchangeBaseUrl - .iter(exchange.baseUrl) - .toArray(); + const availableDenoms: DenominationRecord[] = + await tx.denominations.indexes.byExchangeBaseUrl + .iter(exchange.baseUrl) + .toArray(); const availableAmount = Amounts.sub( refreshGroup.inputPerCoin[coinIndex], @@ -351,7 +355,22 @@ async function refreshMelt( const { newCoinDenoms, oldCoin, oldDenom, refreshGroup, refreshSession } = d; + let exchangeProtocolVersion: ExchangeProtocolVersion; + switch (d.oldDenom.denomPub.cipher) { + case DenomKeyType.LegacyRsa: { + exchangeProtocolVersion = ExchangeProtocolVersion.V9; + break; + } + case DenomKeyType.Rsa: { + exchangeProtocolVersion = ExchangeProtocolVersion.V12; + break; + } + default: + throw Error("unsupported key type"); + } + const derived = await ws.cryptoApi.deriveRefreshSession({ + exchangeProtocolVersion, kappa: 3, meltCoinDenomPubHash: oldCoin.denomPubHash, meltCoinPriv: oldCoin.coinPriv, @@ -531,7 +550,22 @@ async function refreshReveal( norevealIndex, } = d; + let exchangeProtocolVersion: ExchangeProtocolVersion; + switch (d.oldDenom.denomPub.cipher) { + case DenomKeyType.LegacyRsa: { + exchangeProtocolVersion = ExchangeProtocolVersion.V9; + break; + } + case DenomKeyType.Rsa: { + exchangeProtocolVersion = ExchangeProtocolVersion.V12; + break; + } + default: + throw Error("unsupported key type"); + } + const derived = await ws.cryptoApi.deriveRefreshSession({ + exchangeProtocolVersion, kappa: 3, meltCoinDenomPubHash: oldCoin.denomPubHash, meltCoinPriv: oldCoin.coinPriv, diff --git a/packages/taler-wallet-core/src/versions.ts b/packages/taler-wallet-core/src/versions.ts index 9ef298d62..23445b257 100644 --- a/packages/taler-wallet-core/src/versions.ts +++ b/packages/taler-wallet-core/src/versions.ts @@ -19,7 +19,7 @@ * * Uses libtool's current:revision:age versioning. */ -export const WALLET_EXCHANGE_PROTOCOL_VERSION = "10:0:1"; +export const WALLET_EXCHANGE_PROTOCOL_VERSION = "12:0:0"; /** * Protocol version spoken with the merchant.