diff options
author | Florian Dold <florian@dold.me> | 2021-11-17 10:23:22 +0100 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2021-11-17 10:23:30 +0100 |
commit | 9f0429cb2f8ad9cb2e98a787139602d913c1aefa (patch) | |
tree | cda55e2d07a291dd2ff6f243bb423121ecf220b3 /packages/taler-wallet-core/src/crypto | |
parent | a994009d2f094c4d9c12da68dac3abb28bdef4b3 (diff) | |
download | wallet-core-9f0429cb2f8ad9cb2e98a787139602d913c1aefa.tar.xz |
wallet: implement exchange protocol v9
Diffstat (limited to 'packages/taler-wallet-core/src/crypto')
-rw-r--r-- | packages/taler-wallet-core/src/crypto/cryptoTypes.ts | 6 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts | 50 |
2 files changed, 36 insertions, 20 deletions
diff --git a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts index 922fbbfac..7d616ecb6 100644 --- a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts +++ b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts @@ -27,13 +27,13 @@ /** * Imports. */ -import { AmountJson } from "@gnu-taler/taler-util"; +import { AmountJson, DenominationPubKey } from "@gnu-taler/taler-util"; export interface RefreshNewDenomInfo { count: number; value: AmountJson; feeWithdraw: AmountJson; - denomPub: string; + denomPub: DenominationPubKey; } /** @@ -117,7 +117,7 @@ export interface DerivedRefreshSession { export interface DeriveTipRequest { secretSeed: string; - denomPub: string; + denomPub: DenominationPubKey; planchetIndex: number; } diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts index 169d1d9b9..389b98b22 100644 --- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts @@ -35,7 +35,9 @@ import { import { buildSigPS, CoinDepositPermission, + DenomKeyType, FreshCoin, + hashDenomPub, RecoupRequest, RefreshPlanchetInfo, TalerSignaturePurpose, @@ -152,17 +154,20 @@ export class CryptoImplementation { * reserve. */ createPlanchet(req: PlanchetCreationRequest): PlanchetCreationResult { + if (req.denomPub.cipher !== 1) { + throw Error("unsupported cipher"); + } const reservePub = decodeCrock(req.reservePub); const reservePriv = decodeCrock(req.reservePriv); - const denomPub = decodeCrock(req.denomPub); + const denomPubRsa = decodeCrock(req.denomPub.rsa_public_key); const derivedPlanchet = setupWithdrawPlanchet( decodeCrock(req.secretSeed), req.coinIndex, ); const coinPubHash = hash(derivedPlanchet.coinPub); - const ev = rsaBlind(coinPubHash, derivedPlanchet.bks, denomPub); + const ev = rsaBlind(coinPubHash, derivedPlanchet.bks, denomPubRsa); const amountWithFee = Amounts.add(req.value, req.feeWithdraw).amount; - const denomPubHash = hash(denomPub); + const denomPubHash = hashDenomPub(req.denomPub); const evHash = hash(ev); const withdrawRequest = buildSigPS( @@ -182,7 +187,10 @@ export class CryptoImplementation { coinPriv: encodeCrock(derivedPlanchet.coinPriv), coinPub: encodeCrock(derivedPlanchet.coinPub), coinValue: req.value, - denomPub: encodeCrock(denomPub), + denomPub: { + cipher: 1, + rsa_public_key: encodeCrock(denomPubRsa), + }, denomPubHash: encodeCrock(denomPubHash), reservePub: encodeCrock(reservePub), withdrawSig: encodeCrock(sig), @@ -195,8 +203,11 @@ export class CryptoImplementation { * Create a planchet used for tipping, including the private keys. */ createTipPlanchet(req: DeriveTipRequest): DerivedTipPlanchet { + if (req.denomPub.cipher !== 1) { + throw Error("unsupported cipher"); + } const fc = setupTipPlanchet(decodeCrock(req.secretSeed), req.planchetIndex); - const denomPub = decodeCrock(req.denomPub); + const denomPub = decodeCrock(req.denomPub.rsa_public_key); const coinPubHash = hash(fc.coinPub); const ev = rsaBlind(coinPubHash, fc.bks, denomPub); @@ -319,14 +330,9 @@ export class CryptoImplementation { sig: string, masterPub: string, ): boolean { - const h = kdf( - 64, - stringToBytes("exchange-wire-signature"), - stringToBytes(paytoUri + "\0"), - new Uint8Array(0), - ); + const paytoHash = hash(stringToBytes(paytoUri + "\0")); const p = buildSigPS(TalerSignaturePurpose.MASTER_WIRE_DETAILS) - .put(h) + .put(paytoHash) .build(); return eddsaVerify(p, decodeCrock(sig), decodeCrock(masterPub)); } @@ -385,8 +391,11 @@ export class CryptoImplementation { * and deposit permissions for each given coin. */ signDepositPermission(depositInfo: DepositInfo): CoinDepositPermission { + // FIXME: put extensions here if used + const hExt = new Uint8Array(64); const d = buildSigPS(TalerSignaturePurpose.WALLET_COIN_DEPOSIT) .put(decodeCrock(depositInfo.contractTermsHash)) + .put(hExt) .put(decodeCrock(depositInfo.wireInfoHash)) .put(decodeCrock(depositInfo.denomPubHash)) .put(timestampRoundedToBuffer(depositInfo.timestamp)) @@ -394,7 +403,6 @@ export class CryptoImplementation { .put(amountToBuffer(depositInfo.spendAmount)) .put(amountToBuffer(depositInfo.feeDeposit)) .put(decodeCrock(depositInfo.merchantPub)) - .put(decodeCrock(depositInfo.coinPub)) .build(); const coinSig = eddsaSign(d, decodeCrock(depositInfo.coinPriv)); @@ -404,7 +412,10 @@ export class CryptoImplementation { contribution: Amounts.stringify(depositInfo.spendAmount), h_denom: depositInfo.denomPubHash, exchange_url: depositInfo.exchangeBaseUrl, - ub_sig: depositInfo.denomSig, + ub_sig: { + cipher: DenomKeyType.Rsa, + rsa_signature: depositInfo.denomSig.rsa_signature, + }, }; return s; } @@ -455,8 +466,10 @@ export class CryptoImplementation { for (const denomSel of newCoinDenoms) { for (let i = 0; i < denomSel.count; i++) { - const r = decodeCrock(denomSel.denomPub); - sessionHc.update(r); + if (denomSel.denomPub.cipher !== 1) { + throw Error("unsupported cipher"); + } + sessionHc.update(hashDenomPub(denomSel.denomPub)); } } @@ -495,7 +508,10 @@ export class CryptoImplementation { blindingFactor = fresh.bks; } const pubHash = hash(coinPub); - const denomPub = decodeCrock(denomSel.denomPub); + if (denomSel.denomPub.cipher !== 1) { + throw Error("unsupported cipher"); + } + const denomPub = decodeCrock(denomSel.denomPub.rsa_public_key); const ev = rsaBlind(pubHash, blindingFactor, denomPub); const planchet: RefreshPlanchetInfo = { blindingKey: encodeCrock(blindingFactor), |