diff options
Diffstat (limited to 'packages/taler-wallet-core/src/operations')
6 files changed, 116 insertions, 14 deletions
diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts index a66bc2e84..75724dca7 100644 --- a/packages/taler-wallet-core/src/operations/backup/export.ts +++ b/packages/taler-wallet-core/src/operations/backup/export.ts @@ -273,6 +273,7 @@ export async function exportBackup( currency: dp.currency, master_public_key: dp.masterPublicKey, update_clock: dp.updateClock, + protocol_version_range: dp.protocolVersionRange, }); }); diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts index e8e1de0b9..40fa4cdec 100644 --- a/packages/taler-wallet-core/src/operations/backup/import.ts +++ b/packages/taler-wallet-core/src/operations/backup/import.ts @@ -267,6 +267,7 @@ export async function importBackup( currency: backupExchange.currency, masterPublicKey: backupExchange.master_public_key, updateClock: backupExchange.update_clock, + protocolVersionRange: backupExchange.protocol_version_range, }, permanent: true, retryInfo: initRetryInfo(), diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index c170c5469..638af813a 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -23,7 +23,6 @@ import { canonicalizeBaseUrl, codecForExchangeKeysJson, codecForExchangeWireJson, - compare, Denomination, Duration, durationFromSpec, @@ -40,6 +39,7 @@ import { TalerErrorDetails, Timestamp, hashDenomPub, + LibtoolVersion, } from "@gnu-taler/taler-util"; import { decodeCrock, encodeCrock, hash } from "@gnu-taler/taler-util"; import { CryptoApi } from "../crypto/workers/cryptoApi.js"; @@ -365,7 +365,10 @@ async function downloadKeysInfo( const protocolVersion = exchangeKeysJson.version; - const versionRes = compare(WALLET_EXCHANGE_PROTOCOL_VERSION, protocolVersion); + const versionRes = LibtoolVersion.compare( + WALLET_EXCHANGE_PROTOCOL_VERSION, + protocolVersion, + ); if (versionRes?.compatible != true) { const opErr = makeErrorDetails( TalerErrorCode.WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE, @@ -548,6 +551,7 @@ async function updateExchangeFromUrlImpl( masterPublicKey: details.masterPublicKey, // FIXME: only change if pointer really changed updateClock: getTimestampNow(), + protocolVersionRange: keysInfo.protocolVersion, }; await tx.exchanges.put(r); await tx.exchangeDetails.put(details); diff --git a/packages/taler-wallet-core/src/operations/merchants.ts b/packages/taler-wallet-core/src/operations/merchants.ts new file mode 100644 index 000000000..d12417c7c --- /dev/null +++ b/packages/taler-wallet-core/src/operations/merchants.ts @@ -0,0 +1,68 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A.. + + 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/> + */ + +/** + * Imports. + */ +import { + canonicalizeBaseUrl, + Logger, + URL, + codecForMerchantConfigResponse, + LibtoolVersion, +} from "@gnu-taler/taler-util"; +import { InternalWalletState, MerchantInfo } from "../common.js"; +import { readSuccessResponseJsonOrThrow } from "../index.js"; + +const logger = new Logger("taler-wallet-core:merchants.ts"); + +export async function getMerchantInfo( + ws: InternalWalletState, + merchantBaseUrl: string, +): Promise<MerchantInfo> { + const canonBaseUrl = canonicalizeBaseUrl(merchantBaseUrl); + + const existingInfo = ws.merchantInfoCache[canonBaseUrl]; + if (existingInfo) { + return existingInfo; + } + + const configUrl = new URL("config", canonBaseUrl); + const resp = await ws.http.get(configUrl.href); + + const configResp = await readSuccessResponseJsonOrThrow( + resp, + codecForMerchantConfigResponse(), + ); + + logger.info( + `merchant "${canonBaseUrl}" reports protocol ${configResp.version}"`, + ); + + const merchantInfo: MerchantInfo = { + supportsMerchantProtocolV1: !!LibtoolVersion.compare( + "1:0:0", + configResp.version, + )?.compatible, + supportsMerchantProtocolV2: !!LibtoolVersion.compare( + "2:0:0", + configResp.version, + )?.compatible, + }; + + ws.merchantInfoCache[canonBaseUrl] = merchantInfo; + return merchantInfo; +} diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts index 07ce00d2e..0253930ea 100644 --- a/packages/taler-wallet-core/src/operations/tip.ts +++ b/packages/taler-wallet-core/src/operations/tip.ts @@ -27,10 +27,12 @@ import { NotificationType, TipPlanchetDetail, TalerErrorCode, - codecForTipResponse, + codecForMerchantTipResponseV1, Logger, URL, DenomKeyType, + BlindedDenominationSignature, + codecForMerchantTipResponseV2, } from "@gnu-taler/taler-util"; import { DerivedTipPlanchet } from "../crypto/cryptoTypes.js"; import { @@ -304,31 +306,57 @@ async function processTipImpl( return; } - const response = await readSuccessResponseJsonOrThrow( - merchantResp, - codecForTipResponse(), + // FIXME: Do this earlier? + const merchantInfo = await ws.merchantOps.getMerchantInfo( + ws, + tipRecord.merchantBaseUrl, ); - if (response.blind_sigs.length !== planchets.length) { + let blindedSigs: BlindedDenominationSignature[] = []; + + if (merchantInfo.supportsMerchantProtocolV2) { + const response = await readSuccessResponseJsonOrThrow( + merchantResp, + codecForMerchantTipResponseV2(), + ); + blindedSigs = response.blind_sigs.map((x) => x.blind_sig); + } else if (merchantInfo.supportsMerchantProtocolV1) { + const response = await readSuccessResponseJsonOrThrow( + merchantResp, + codecForMerchantTipResponseV1(), + ); + blindedSigs = response.blind_sigs.map((x) => ({ + cipher: DenomKeyType.Rsa, + blinded_rsa_signature: x.blind_sig, + })); + } else { + throw Error("unsupported merchant protocol version"); + } + + if (blindedSigs.length !== planchets.length) { throw Error("number of tip responses does not match requested planchets"); } const newCoinRecords: CoinRecord[] = []; - for (let i = 0; i < response.blind_sigs.length; i++) { - const blindedSig = response.blind_sigs[i].blind_sig; + for (let i = 0; i < blindedSigs.length; i++) { + const blindedSig = blindedSigs[i]; const denom = denomForPlanchet[i]; checkLogicInvariant(!!denom); const planchet = planchets[i]; checkLogicInvariant(!!planchet); - if (denom.denomPub.cipher !== 1) { + if (denom.denomPub.cipher !== DenomKeyType.Rsa) { + throw Error("unsupported cipher"); + } + + if (blindedSig.cipher !== DenomKeyType.Rsa) { throw Error("unsupported cipher"); } const denomSigRsa = await ws.cryptoApi.rsaUnblind( - blindedSig, + blindedSig.blinded_rsa_signature, planchet.blindingKey, denom.denomPub.rsa_public_key, ); diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 57bd49d23..a5a8653c6 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -24,7 +24,6 @@ import { codecForTalerConfigResponse, codecForWithdrawOperationStatusResponse, codecForWithdrawResponse, - compare, durationFromSpec, ExchangeListItem, getDurationRemaining, @@ -42,6 +41,7 @@ import { WithdrawUriInfoResponse, VersionMatchResult, DenomKeyType, + LibtoolVersion, } from "@gnu-taler/taler-util"; import { CoinRecord, @@ -285,7 +285,7 @@ export async function getBankWithdrawalInfo( codecForTalerConfigResponse(), ); - const versionRes = compare( + const versionRes = LibtoolVersion.compare( WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, config.version, ); @@ -985,7 +985,7 @@ export async function getExchangeWithdrawalInfo( let versionMatch; if (exchangeDetails.protocolVersion) { - versionMatch = compare( + versionMatch = LibtoolVersion.compare( WALLET_EXCHANGE_PROTOCOL_VERSION, exchangeDetails.protocolVersion, ); |