aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/taler-wallet-core/src/crypto/talerCrypto.ts19
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts22
-rw-r--r--packages/taler-wallet-core/src/operations/backup.ts44
-rw-r--r--packages/taler-wallet-core/src/operations/reserves.ts1
-rw-r--r--packages/taler-wallet-core/src/operations/tip.ts8
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts2
-rw-r--r--packages/taler-wallet-core/src/types/backupTypes.ts13
-rw-r--r--packages/taler-wallet-core/src/types/dbTypes.ts5
-rw-r--r--packages/taler-wallet-core/src/types/walletTypes.ts2
-rw-r--r--packages/taler-wallet-core/src/util/invariants.ts10
10 files changed, 91 insertions, 35 deletions
diff --git a/packages/taler-wallet-core/src/crypto/talerCrypto.ts b/packages/taler-wallet-core/src/crypto/talerCrypto.ts
index 095957982..d28f11174 100644
--- a/packages/taler-wallet-core/src/crypto/talerCrypto.ts
+++ b/packages/taler-wallet-core/src/crypto/talerCrypto.ts
@@ -390,6 +390,25 @@ export function setupRefreshPlanchet(
};
}
+export function setupWithdrawPlanchet(
+ secretSeed: Uint8Array,
+ coinNumber: number,
+): FreshCoin {
+ const info = stringToBytes("taler-withdrawal-coin-derivation");
+ const saltArrBuf = new ArrayBuffer(4);
+ const salt = new Uint8Array(saltArrBuf);
+ const saltDataView = new DataView(saltArrBuf);
+ saltDataView.setUint32(0, coinNumber);
+ const out = kdf(64, secretSeed, salt, info);
+ const coinPriv = out.slice(0, 32);
+ const bks = out.slice(32, 64);
+ return {
+ bks,
+ coinPriv,
+ coinPub: eddsaGetPublic(coinPriv),
+ };
+}
+
export function setupTipPlanchet(
secretSeed: Uint8Array,
coinNumber: number,
diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
index 4f553c502..fc8b53eb7 100644
--- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts
@@ -61,13 +61,11 @@ import {
rsaVerify,
setupRefreshTransferPub,
setupTipPlanchet,
+ setupWithdrawPlanchet,
} from "../talerCrypto";
import { randomBytes } from "../primitives/nacl-fast";
import { kdf } from "../primitives/kdf";
-import {
- Timestamp,
- timestampTruncateToSecond,
-} from "../../util/time";
+import { Timestamp, timestampTruncateToSecond } from "../../util/time";
import { Logger } from "../../util/logging";
import {
@@ -161,10 +159,12 @@ export class CryptoImplementation {
const reservePub = decodeCrock(req.reservePub);
const reservePriv = decodeCrock(req.reservePriv);
const denomPub = decodeCrock(req.denomPub);
- const coinKeyPair = createEddsaKeyPair();
- const blindingFactor = createBlindingKeySecret();
- const coinPubHash = hash(coinKeyPair.eddsaPub);
- const ev = rsaBlind(coinPubHash, blindingFactor, denomPub);
+ const derivedPlanchet = setupWithdrawPlanchet(
+ decodeCrock(req.secretSeed),
+ req.coinIndex,
+ );
+ const coinPubHash = hash(derivedPlanchet.coinPub);
+ const ev = rsaBlind(coinPubHash, derivedPlanchet.bks, denomPub);
const amountWithFee = Amounts.add(req.value, req.feeWithdraw).amount;
const denomPubHash = hash(denomPub);
const evHash = hash(ev);
@@ -179,10 +179,10 @@ export class CryptoImplementation {
const sig = eddsaSign(withdrawRequest, reservePriv);
const planchet: PlanchetCreationResult = {
- blindingKey: encodeCrock(blindingFactor),
+ blindingKey: encodeCrock(derivedPlanchet.bks),
coinEv: encodeCrock(ev),
- coinPriv: encodeCrock(coinKeyPair.eddsaPriv),
- coinPub: encodeCrock(coinKeyPair.eddsaPub),
+ coinPriv: encodeCrock(derivedPlanchet.coinPriv),
+ coinPub: encodeCrock(derivedPlanchet.coinPub),
coinValue: req.value,
denomPub: encodeCrock(denomPub),
denomPubHash: encodeCrock(denomPubHash),
diff --git a/packages/taler-wallet-core/src/operations/backup.ts b/packages/taler-wallet-core/src/operations/backup.ts
index 1e5aa542d..f071b6d08 100644
--- a/packages/taler-wallet-core/src/operations/backup.ts
+++ b/packages/taler-wallet-core/src/operations/backup.ts
@@ -198,17 +198,17 @@ export async function exportBackup(
const withdrawalGroups = (withdrawalGroupsByReserve[
wg.reservePub
] ??= []);
- // FIXME: finish!
- // withdrawalGroups.push({
- // raw_withdrawal_amount: Amounts.stringify(wg.rawWithdrawalAmount),
- // selected_denoms: wg.denomsSel.selectedDenoms.map((x) => ({
- // count: x.count,
- // denom_pub_hash: x.denomPubHash,
- // })),
- // timestamp_start: wg.timestampStart,
- // timestamp_finish: wg.timestampFinish,
- // withdrawal_group_id: wg.withdrawalGroupId,
- // });
+ withdrawalGroups.push({
+ raw_withdrawal_amount: Amounts.stringify(wg.rawWithdrawalAmount),
+ selected_denoms: wg.denomsSel.selectedDenoms.map((x) => ({
+ count: x.count,
+ denom_pub_hash: x.denomPubHash,
+ })),
+ timestamp_start: wg.timestampStart,
+ timestamp_finish: wg.timestampFinish,
+ withdrawal_group_id: wg.withdrawalGroupId,
+ secret_seed: wg.secretSeed
+ });
});
await tx.iter(Stores.reserves).forEach((reserve) => {
@@ -572,11 +572,29 @@ export async function encryptBackup(
throw Error("not implemented");
}
-export function importBackup(
+export async function importBackup(
ws: InternalWalletState,
backupRequest: BackupRequest,
): Promise<void> {
- throw Error("not implemented");
+ await provideBackupState(ws);
+ return ws.db.runWithWriteTransaction(
+ [
+ Stores.config,
+ Stores.exchanges,
+ Stores.coins,
+ Stores.denominations,
+ Stores.purchases,
+ Stores.proposals,
+ Stores.refreshGroups,
+ Stores.backupProviders,
+ Stores.tips,
+ Stores.recoupGroups,
+ Stores.reserves,
+ Stores.withdrawalGroups,
+ ],
+ async (tx) => {
+
+ });
}
function deriveAccountKeyPair(
diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts
index 95c38120c..4e4db1fc9 100644
--- a/packages/taler-wallet-core/src/operations/reserves.ts
+++ b/packages/taler-wallet-core/src/operations/reserves.ts
@@ -623,6 +623,7 @@ async function updateReserve(
retryInfo: initRetryInfo(),
lastError: undefined,
denomsSel: denomSelectionInfoToState(denomSelInfo),
+ secretSeed: encodeCrock(getRandomBytes(64)),
};
newReserve.lastError = undefined;
diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts
index f47f76623..f683999bc 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -48,7 +48,7 @@ import {
} from "../util/http";
import { URL } from "../util/url";
import { Logger } from "../util/logging";
-import { checkDbInvariant } from "../util/invariants";
+import { checkDbInvariant, checkLogicInvariant } from "../util/invariants";
import { TalerErrorCode } from "../TalerErrorCode";
import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries";
import { j2s } from "../util/helpers";
@@ -221,13 +221,13 @@ async function processTipImpl(
dh.denomPubHash,
]);
checkDbInvariant(!!denom, "denomination should be in database");
- denomForPlanchet[planchets.length] = denom;
for (let i = 0; i < dh.count; i++) {
const p = await ws.cryptoApi.createTipPlanchet({
- denomPub: dh.denomPubHash,
+ denomPub: denom.denomPub,
planchetIndex: planchets.length,
secretSeed: tipRecord.secretSeed,
});
+ denomForPlanchet[planchets.length] = denom;
planchets.push(p);
planchetsDetail.push({
coin_ev: p.coinEv,
@@ -275,7 +275,9 @@ async function processTipImpl(
const blindedSig = response.blind_sigs[i].blind_sig;
const denom = denomForPlanchet[i];
+ checkLogicInvariant(!!denom);
const planchet = planchets[i];
+ checkLogicInvariant(!!planchet);
const denomSig = await ws.cryptoApi.rsaUnblind(
blindedSig,
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 758b80787..c2dfcd1c4 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -284,6 +284,8 @@ async function processPlanchetGenerate(
reservePriv: reserve.reservePriv,
reservePub: reserve.reservePub,
value: denom.value,
+ coinIndex: coinIdx,
+ secretSeed: withdrawalGroup.secretSeed,
});
const newPlanchet: PlanchetRecord = {
blindingKey: r.blindingKey,
diff --git a/packages/taler-wallet-core/src/types/backupTypes.ts b/packages/taler-wallet-core/src/types/backupTypes.ts
index a3261ae35..d40d4fa6c 100644
--- a/packages/taler-wallet-core/src/types/backupTypes.ts
+++ b/packages/taler-wallet-core/src/types/backupTypes.ts
@@ -626,6 +626,11 @@ export interface BackupWithdrawalGroup {
withdrawal_group_id: string;
/**
+ * Secret seed to derive the planchets.
+ */
+ secret_seed: string;
+
+ /**
* When was the withdrawal operation started started?
* Timestamp in milliseconds.
*/
@@ -653,14 +658,6 @@ export interface BackupWithdrawalGroup {
denom_pub_hash: string;
count: number;
}[];
-
- /**
- * One planchet/coin for each selected denomination.
- */
- planchets: {
- blinding_key: string;
- coin_priv: string;
- }[];
}
export enum BackupRefundState {
diff --git a/packages/taler-wallet-core/src/types/dbTypes.ts b/packages/taler-wallet-core/src/types/dbTypes.ts
index 71a591310..7ba3b8604 100644
--- a/packages/taler-wallet-core/src/types/dbTypes.ts
+++ b/packages/taler-wallet-core/src/types/dbTypes.ts
@@ -1322,6 +1322,11 @@ export interface DenomSelectionState {
export interface WithdrawalGroupRecord {
withdrawalGroupId: string;
+ /**
+ * Secret seed used to derive planchets.
+ */
+ secretSeed: string;
+
reservePub: string;
exchangeBaseUrl: string;
diff --git a/packages/taler-wallet-core/src/types/walletTypes.ts b/packages/taler-wallet-core/src/types/walletTypes.ts
index 7dc675b38..1b962e1c4 100644
--- a/packages/taler-wallet-core/src/types/walletTypes.ts
+++ b/packages/taler-wallet-core/src/types/walletTypes.ts
@@ -557,6 +557,8 @@ export interface PlanchetCreationResult {
}
export interface PlanchetCreationRequest {
+ secretSeed: string;
+ coinIndex: number;
value: AmountJson;
feeWithdraw: AmountJson;
denomPub: string;
diff --git a/packages/taler-wallet-core/src/util/invariants.ts b/packages/taler-wallet-core/src/util/invariants.ts
index fa381d333..b788d044e 100644
--- a/packages/taler-wallet-core/src/util/invariants.ts
+++ b/packages/taler-wallet-core/src/util/invariants.ts
@@ -27,3 +27,13 @@ export function checkDbInvariant(b: boolean, m?: string): asserts b {
}
}
}
+
+export function checkLogicInvariant(b: boolean, m?: string): asserts b {
+ if (!b) {
+ if (m) {
+ throw Error(`BUG: logic invariant failed (${m})`);
+ } else {
+ throw Error("BUG: logic invariant failed");
+ }
+ }
+}