gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: wallet-core: deterministic p2


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: deterministic p2p contract encryption
Date: Tue, 06 Jun 2023 15:00:31 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 474a171f5 wallet-core: deterministic p2p contract encryption
474a171f5 is described below

commit 474a171f5e6684ab7d11bb2987fc90fe6e1b37c8
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Jun 6 15:00:10 2023 +0200

    wallet-core: deterministic p2p contract encryption
---
 packages/taler-util/src/taler-crypto.ts            |   6 +-
 .../src/crypto/cryptoImplementation.ts             |   2 +
 .../taler-wallet-core/src/crypto/cryptoTypes.ts    |   3 +
 packages/taler-wallet-core/src/db.ts               |  13 +++
 .../src/operations/pay-peer-pull-credit.ts         |   4 +
 .../src/operations/pay-peer-push-debit.ts          | 116 +++++++++++++--------
 6 files changed, 98 insertions(+), 46 deletions(-)

diff --git a/packages/taler-util/src/taler-crypto.ts 
b/packages/taler-util/src/taler-crypto.ts
index c4eb925f7..ed3b82cd0 100644
--- a/packages/taler-util/src/taler-crypto.ts
+++ b/packages/taler-util/src/taler-crypto.ts
@@ -1465,6 +1465,7 @@ export function encryptContractForMerge(
   contractPriv: ContractPrivateKey,
   mergePriv: MergePrivateKey,
   contractTerms: any,
+  nonce: EncryptionNonce,
 ): Promise<OpaqueData> {
   const contractTermsCanon = canonicalJson(contractTerms) + "\0";
   const contractTermsBytes = stringToBytes(contractTermsCanon);
@@ -1476,13 +1477,14 @@ export function encryptContractForMerge(
     contractTermsCompressed,
   ]);
   const key = keyExchangeEcdhEddsa(contractPriv, pursePub);
-  return encryptWithDerivedKey(getRandomBytesF(24), key, data, mergeSalt);
+  return encryptWithDerivedKey(nonce, key, data, mergeSalt);
 }
 
 export function encryptContractForDeposit(
   pursePub: PursePublicKey,
   contractPriv: ContractPrivateKey,
   contractTerms: any,
+  nonce: EncryptionNonce,
 ): Promise<OpaqueData> {
   const contractTermsCanon = canonicalJson(contractTerms) + "\0";
   const contractTermsBytes = stringToBytes(contractTermsCanon);
@@ -1493,7 +1495,7 @@ export function encryptContractForDeposit(
     contractTermsCompressed,
   ]);
   const key = keyExchangeEcdhEddsa(contractPriv, pursePub);
-  return encryptWithDerivedKey(getRandomBytesF(24), key, data, depositSalt);
+  return encryptWithDerivedKey(nonce, key, data, depositSalt);
 }
 
 export interface DecryptForMergeResult {
diff --git a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts 
b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts
index c0c8e0d01..15ca1ea95 100644
--- a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts
+++ b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts
@@ -1495,6 +1495,7 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
       decodeCrock(req.contractPriv),
       decodeCrock(req.mergePriv),
       req.contractTerms,
+      decodeCrock(req.nonce),
     );
     const sigBlob = buildSigPS(TalerSignaturePurpose.WALLET_PURSE_ECONTRACT)
       .put(hash(enc))
@@ -1531,6 +1532,7 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
       decodeCrock(req.pursePub),
       decodeCrock(req.contractPriv),
       req.contractTerms,
+      decodeCrock(req.nonce),
     );
     const sigBlob = buildSigPS(TalerSignaturePurpose.WALLET_PURSE_ECONTRACT)
       .put(hash(enc))
diff --git a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts 
b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts
index 930db03a8..7eaa4a55a 100644
--- a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts
+++ b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts
@@ -181,6 +181,7 @@ export interface EncryptContractRequest {
   pursePub: string;
   pursePriv: string;
   mergePriv: string;
+  nonce: string;
 }
 
 export interface EncryptContractResponse {
@@ -195,6 +196,8 @@ export interface EncryptContractForDepositRequest {
 
   pursePub: string;
   pursePriv: string;
+
+  nonce: string;
 }
 
 export interface EncryptContractForDepositResponse {
diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index a5db49649..c4cdf769b 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -1839,6 +1839,14 @@ export interface PeerPushPaymentInitiationRecord {
   contractPriv: string;
   contractPub: string;
 
+  /**
+   * 24 byte nonce.
+   */
+  contractEncNonce: string;
+
+  /**
+   * FIXME: Put those in a different object store!
+   */
   contractTerms: PeerContractTerms;
 
   purseExpiration: TalerProtocolTimestamp;
@@ -1911,6 +1919,11 @@ export interface PeerPullPaymentInitiationRecord {
   contractPub: string;
   contractPriv: string;
 
+  contractEncNonce: string;
+
+  /**
+   * FIXME: Put in separate object store!
+   */
   contractTerms: PeerContractTerms;
 
   mergeTimestamp: TalerPreciseTimestamp;
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts 
b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
index a85df66d2..fc2718ce5 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
@@ -405,6 +405,7 @@ export async function processPeerPullCredit(
     contractTerms: pullIni.contractTerms,
     pursePriv: pullIni.pursePriv,
     pursePub: pullIni.pursePub,
+    nonce: pullIni.contractEncNonce,
   });
 
   const purseExpiration = pullIni.contractTerms.purse_expiration;
@@ -690,6 +691,8 @@ export async function initiatePeerPullPayment(
   const mergeReserveRowId = mergeReserveInfo.rowId;
   checkDbInvariant(!!mergeReserveRowId);
 
+  const contractEncNonce = encodeCrock(getRandomBytes(24));
+
   const wi = await getExchangeWithdrawalInfo(
     ws,
     exchangeBaseUrl,
@@ -711,6 +714,7 @@ export async function initiatePeerPullPayment(
         status: PeerPullPaymentInitiationStatus.PendingCreatePurse,
         contractTerms: contractTerms,
         mergeTimestamp,
+        contractEncNonce,
         mergeReserveRowId: mergeReserveRowId,
         contractPriv: contractKeyPair.priv,
         contractPub: contractKeyPair.pub,
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts 
b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts
index ac0aa9c87..a03980d46 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts
@@ -34,6 +34,10 @@ import {
   TransactionMinorState,
   TransactionState,
   TransactionType,
+  decodeCrock,
+  encodeCrock,
+  getRandomBytes,
+  hash,
   j2s,
   stringifyTalerUri,
 } from "@gnu-taler/taler-util";
@@ -57,11 +61,7 @@ import {
   OperationAttemptResultType,
   constructTaskIdentifier,
 } from "../util/retries.js";
-import {
-  runLongpollAsync,
-  spendCoins,
-  runOperationWithErrorReporting,
-} from "./common.js";
+import { runLongpollAsync, spendCoins } from "./common.js";
 import {
   constructTransactionIdentifier,
   notifyTransition,
@@ -69,6 +69,7 @@ import {
 } from "./transactions.js";
 import { assertUnreachable } from "../util/assertUnreachable.js";
 import { checkLogicInvariant } from "../util/invariants.js";
+import { EncryptContractRequest } from "../crypto/cryptoTypes.js";
 
 const logger = new Logger("pay-peer-push-debit.ts");
 
@@ -100,6 +101,7 @@ async function processPeerPushDebitCreateReserve(
   ws: InternalWalletState,
   peerPushInitiation: PeerPushPaymentInitiationRecord,
 ): Promise<OperationAttemptResult> {
+  logger.info("processing peer-push-debit pending(create-reserve)");
   const pursePub = peerPushInitiation.pursePub;
   const purseExpiration = peerPushInitiation.purseExpiration;
   const hContractTerms = peerPushInitiation.contractTermsHash;
@@ -124,32 +126,49 @@ async function processPeerPushDebitCreateReserve(
     coins,
   });
 
-  const econtractResp = await ws.cryptoApi.encryptContractForMerge({
+  const encryptContractRequest: EncryptContractRequest = {
     contractTerms: peerPushInitiation.contractTerms,
     mergePriv: peerPushInitiation.mergePriv,
     pursePriv: peerPushInitiation.pursePriv,
     pursePub: peerPushInitiation.pursePub,
     contractPriv: peerPushInitiation.contractPriv,
     contractPub: peerPushInitiation.contractPub,
-  });
+    nonce: peerPushInitiation.contractEncNonce,
+  };
+
+  logger.info(`encrypt contract request: ${j2s(encryptContractRequest)}`);
+
+  const econtractResp = await ws.cryptoApi.encryptContractForMerge(
+    encryptContractRequest,
+  );
+
+  const econtractHash = encodeCrock(
+    hash(decodeCrock(econtractResp.econtract.econtract)),
+  );
+
+  logger.info(`econtract hash: ${econtractHash}`);
 
   const createPurseUrl = new URL(
     `purses/${peerPushInitiation.pursePub}/create`,
     peerPushInitiation.exchangeBaseUrl,
   );
 
+  const reqBody = {
+    amount: peerPushInitiation.amount,
+    merge_pub: peerPushInitiation.mergePub,
+    purse_sig: purseSigResp.sig,
+    h_contract_terms: hContractTerms,
+    purse_expiration: purseExpiration,
+    deposits: depositSigsResp.deposits,
+    min_age: 0,
+    econtract: econtractResp.econtract,
+  };
+
+  logger.info(`request body: ${j2s(reqBody)}`);
+
   const httpResp = await ws.http.fetch(createPurseUrl.href, {
     method: "POST",
-    body: {
-      amount: peerPushInitiation.amount,
-      merge_pub: peerPushInitiation.mergePub,
-      purse_sig: purseSigResp.sig,
-      h_contract_terms: hContractTerms,
-      purse_expiration: purseExpiration,
-      deposits: depositSigsResp.deposits,
-      min_age: 0,
-      econtract: econtractResp.econtract,
-    },
+    body: reqBody,
   });
 
   const resp = await httpResp.json();
@@ -157,24 +176,16 @@ async function processPeerPushDebitCreateReserve(
   logger.info(`resp: ${j2s(resp)}`);
 
   if (httpResp.status !== HttpStatusCode.Ok) {
+    // FIXME: do proper error reporting
     throw Error("got error response from exchange");
   }
 
-  await ws.db
-    .mktx((x) => [x.peerPushPaymentInitiations])
-    .runReadWrite(async (tx) => {
-      const ppi = await tx.peerPushPaymentInitiations.get(pursePub);
-      if (!ppi) {
-        return;
-      }
-      ppi.status = PeerPushPaymentInitiationStatus.Done;
-      await tx.peerPushPaymentInitiations.put(ppi);
-    });
+  await transitionPeerPushDebitTransaction(ws, pursePub, {
+    stFrom: PeerPushPaymentInitiationStatus.PendingCreatePurse,
+    stTo: PeerPushPaymentInitiationStatus.PendingReady,
+  });
 
-  return {
-    type: OperationAttemptResultType.Finished,
-    result: undefined,
-  };
+  return OperationAttemptResult.finishedEmpty();
 }
 
 async function processPeerPushDebitAbortingDeletePurse(
@@ -278,6 +289,7 @@ async function transitionPeerPushDebitTransaction(
       const oldTxState = computePeerPushDebitTransactionState(ppiRec);
       ppiRec.status = transitionSpec.stTo;
       const newTxState = computePeerPushDebitTransactionState(ppiRec);
+      // FIXME: We don't transition here?!
       return {
         oldTxState,
         newTxState,
@@ -341,6 +353,7 @@ async function processPeerPushDebitReady(
   ws: InternalWalletState,
   peerPushInitiation: PeerPushPaymentInitiationRecord,
 ): Promise<OperationAttemptResult> {
+  logger.info("processing peer-push-debit pending(ready)");
   const pursePub = peerPushInitiation.pursePub;
   const retryTag = constructTaskIdentifier({
     tag: PendingTaskType.PeerPushDebit,
@@ -434,6 +447,12 @@ export async function processPeerPushDebit(
       return processPeerPushDebitAbortingDeletePurse(ws, peerPushInitiation);
     case PeerPushPaymentInitiationStatus.AbortingRefresh:
       return processPeerPushDebitAbortingRefresh(ws, peerPushInitiation);
+    default: {
+      const txState = computePeerPushDebitTransactionState(peerPushInitiation);
+      logger.warn(
+        `not processing peer-push-debit transaction in state ${j2s(txState)}`,
+      );
+    }
   }
 
   return {
@@ -482,7 +501,16 @@ export async function initiatePeerPushDebit(
     coinSelRes.result.coins,
   );
 
-  await ws.db
+  const pursePub = pursePair.pub;
+
+  const transactionId = constructTaskIdentifier({
+    tag: PendingTaskType.PeerPushDebit,
+    pursePub,
+  });
+
+  const contractEncNonce = encodeCrock(getRandomBytes(24));
+
+  const transitionInfo = await ws.db
     .mktx((x) => [
       x.exchanges,
       x.contractTerms,
@@ -509,7 +537,7 @@ export async function initiatePeerPushDebit(
         refreshReason: RefreshReason.PayPeerPush,
       });
 
-      await tx.peerPushPaymentInitiations.add({
+      const ppi: PeerPushPaymentInitiationRecord = {
         amount: Amounts.stringify(instructedAmount),
         contractPriv: contractKeyPair.priv,
         contractPub: contractKeyPair.pub,
@@ -523,27 +551,28 @@ export async function initiatePeerPushDebit(
         timestampCreated: TalerPreciseTimestamp.now(),
         status: PeerPushPaymentInitiationStatus.PendingCreatePurse,
         contractTerms: contractTerms,
+        contractEncNonce,
         coinSel: {
           coinPubs: sel.coins.map((x) => x.coinPub),
           contributions: sel.coins.map((x) => x.contribution),
         },
         totalCost: Amounts.stringify(totalAmount),
-      });
+      };
+
+      await tx.peerPushPaymentInitiations.add(ppi);
 
       await tx.contractTerms.put({
         h: hContractTerms,
         contractTermsRaw: contractTerms,
       });
-    });
 
-  const taskId = constructTaskIdentifier({
-    tag: PendingTaskType.PeerPushDebit,
-    pursePub: pursePair.pub,
-  });
-
-  await runOperationWithErrorReporting(ws, taskId, async () => {
-    return await processPeerPushDebit(ws, pursePair.pub);
-  });
+      const newTxState = computePeerPushDebitTransactionState(ppi);
+      return {
+        oldTxState: { major: TransactionMajorState.None },
+        newTxState,
+      };
+    });
+  notifyTransition(ws, transactionId, transitionInfo);
 
   return {
     contractPriv: contractKeyPair.priv,
@@ -903,4 +932,3 @@ export function computePeerPushDebitTransactionState(
       };
   }
 }
-

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]