summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/crypto')
-rw-r--r--packages/taler-wallet-core/src/crypto/cryptoImplementation.ts76
-rw-r--r--packages/taler-wallet-core/src/crypto/cryptoTypes.ts2
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts4
3 files changed, 73 insertions, 9 deletions
diff --git a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts
index fa754e354..052d50ca7 100644
--- a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts
+++ b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts
@@ -69,6 +69,10 @@ import {
kdf,
ecdheGetPublic,
getRandomBytes,
+ AgeCommitmentProof,
+ AgeRestriction,
+ hashCoinPub,
+ HashCodeString,
} from "@gnu-taler/taler-util";
import bigint from "big-integer";
import { DenominationRecord, TipCoinSource, WireFee } from "../db.js";
@@ -82,7 +86,7 @@ import {
SignTrackTransactionRequest,
} from "./cryptoTypes.js";
-//const logger = new Logger("cryptoImplementation.ts");
+const logger = new Logger("cryptoImplementation.ts");
/**
* Interface for (asynchronous) cryptographic operations that
@@ -547,12 +551,34 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
const denomPub = req.denomPub;
if (denomPub.cipher === DenomKeyType.Rsa) {
const reservePub = decodeCrock(req.reservePub);
- const denomPubRsa = decodeCrock(denomPub.rsa_public_key);
const derivedPlanchet = await tci.setupWithdrawalPlanchet(tci, {
coinNumber: req.coinIndex,
secretSeed: req.secretSeed,
});
- const coinPubHash = hash(decodeCrock(derivedPlanchet.coinPub));
+
+ let maybeAcp: AgeCommitmentProof | undefined = undefined;
+ let maybeAgeCommitmentHash: string | undefined = undefined;
+ if (req.restrictAge) {
+ if (denomPub.age_mask === 0) {
+ throw Error(
+ "requested age restriction for a denomination that does not support age restriction",
+ );
+ }
+ logger.info("creating age-restricted planchet");
+ maybeAcp = await AgeRestriction.restrictionCommit(
+ denomPub.age_mask,
+ req.restrictAge,
+ );
+ maybeAgeCommitmentHash = AgeRestriction.hashCommitment(
+ maybeAcp.commitment,
+ );
+ }
+
+ const coinPubHash = hashCoinPub(
+ derivedPlanchet.coinPub,
+ maybeAgeCommitmentHash,
+ );
+
const blindResp = await tci.rsaBlind(tci, {
bks: derivedPlanchet.bks,
hm: encodeCrock(coinPubHash),
@@ -589,6 +615,7 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
reservePub: encodeCrock(reservePub),
withdrawSig: sigResult.sig,
coinEvHash: encodeCrock(evHash),
+ ageCommitmentProof: maybeAcp,
};
return planchet;
} else {
@@ -880,7 +907,23 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
): Promise<CoinDepositPermission> {
// FIXME: put extensions here if used
const hExt = new Uint8Array(64);
- const hAgeCommitment = new Uint8Array(32);
+ let hAgeCommitment: Uint8Array;
+ let maybeAgeCommitmentHash: string | undefined = undefined;
+ let minimumAgeSig: string | undefined = undefined;
+ if (depositInfo.ageCommitmentProof) {
+ const ach = AgeRestriction.hashCommitment(
+ depositInfo.ageCommitmentProof.commitment,
+ );
+ maybeAgeCommitmentHash = ach;
+ hAgeCommitment = decodeCrock(ach);
+ minimumAgeSig = AgeRestriction.commitmentAttest(
+ depositInfo.ageCommitmentProof,
+ depositInfo.requiredMinimumAge!,
+ );
+ } else {
+ // All zeros.
+ hAgeCommitment = new Uint8Array(32);
+ }
let d: Uint8Array;
if (depositInfo.denomKeyType === DenomKeyType.Rsa) {
d = buildSigPS(TalerSignaturePurpose.WALLET_COIN_DEPOSIT)
@@ -914,6 +957,8 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
cipher: DenomKeyType.Rsa,
rsa_signature: depositInfo.denomSig.rsa_signature,
},
+ age_commitment: depositInfo.ageCommitmentProof?.commitment.publicKeys,
+ minimum_age_sig: minimumAgeSig,
};
return s;
} else {
@@ -999,10 +1044,19 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
coinNumber: coinIndex,
transferSecret: transferSecretRes.h,
});
+ let newAc: AgeCommitmentProof | undefined = undefined;
+ let newAch: HashCodeString | undefined = undefined;
+ if (req.meltCoinAgeCommitmentProof) {
+ newAc = await AgeRestriction.commitmentDerive(
+ req.meltCoinAgeCommitmentProof,
+ transferSecretRes.h,
+ );
+ newAch = AgeRestriction.hashCommitment(newAc.commitment);
+ }
coinPriv = decodeCrock(fresh.coinPriv);
coinPub = decodeCrock(fresh.coinPub);
blindingFactor = decodeCrock(fresh.bks);
- const coinPubHash = hash(coinPub);
+ const coinPubHash = hashCoinPub(fresh.coinPub, newAch);
if (denomSel.denomPub.cipher !== DenomKeyType.Rsa) {
throw Error("unsupported cipher, can't create refresh session");
}
@@ -1035,8 +1089,16 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
const sessionHash = sessionHc.finish();
let confirmData: Uint8Array;
- // FIXME: fill in age commitment
- const hAgeCommitment = new Uint8Array(32);
+ let hAgeCommitment: Uint8Array;
+ if (req.meltCoinAgeCommitmentProof) {
+ hAgeCommitment = decodeCrock(
+ AgeRestriction.hashCommitment(
+ req.meltCoinAgeCommitmentProof.commitment,
+ ),
+ );
+ } else {
+ hAgeCommitment = new Uint8Array(32);
+ }
confirmData = buildSigPS(TalerSignaturePurpose.WALLET_COIN_MELT)
.put(sessionHash)
.put(decodeCrock(meltCoinDenomPubHash))
diff --git a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts
index deff15071..fe5dbcec6 100644
--- a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts
+++ b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts
@@ -28,6 +28,7 @@
* Imports.
*/
import {
+ AgeCommitmentProof,
AmountJson,
CoinEnvelope,
DenominationPubKey,
@@ -55,6 +56,7 @@ export interface DeriveRefreshSessionRequest {
meltCoinPub: string;
meltCoinPriv: string;
meltCoinDenomPubHash: string;
+ meltCoinAgeCommitmentProof?: AgeCommitmentProof;
newCoinDenoms: RefreshNewDenomInfo[];
feeRefresh: AmountJson;
}
diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts
index f6c8ae61e..2ef0d7c69 100644
--- a/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts
+++ b/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts
@@ -321,9 +321,9 @@ export class CryptoDispatcher {
return new Promise<T>((resolve, reject) => {
let timedOut = false;
const timeout = timer.after(5000, () => {
- logger.warn("crypto RPC call timed out");
+ logger.warn(`crypto RPC call ('${operation}') timed out`);
timedOut = true;
- reject(new Error("crypto RPC call timed out"));
+ reject(new Error(`crypto RPC call ('${operation}') timed out`));
});
p.then((x) => {
if (timedOut) {