move some more crypto to taler-util package

This commit is contained in:
Florian Dold 2021-10-18 21:48:22 +02:00
parent 3a69f27412
commit 269022a526
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
11 changed files with 208 additions and 80 deletions

View File

@ -5,7 +5,9 @@ import {
encodeCrock, encodeCrock,
getRandomBytes, getRandomBytes,
kdf, kdf,
kdfKw,
secretbox, secretbox,
crypto_sign_keyPair_fromSeed,
stringToBytes, stringToBytes,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { argon2id } from "hash-wasm"; import { argon2id } from "hash-wasm";
@ -25,6 +27,8 @@ export type EncryptedKeyShare = Flavor<string, "EncryptedKeyShare">;
export type EncryptedTruth = Flavor<string, "EncryptedTruth">; export type EncryptedTruth = Flavor<string, "EncryptedTruth">;
export type EncryptedCoreSecret = Flavor<string, "EncryptedCoreSecret">; export type EncryptedCoreSecret = Flavor<string, "EncryptedCoreSecret">;
export type EncryptedMasterKey = Flavor<string, "EncryptedMasterKey">; export type EncryptedMasterKey = Flavor<string, "EncryptedMasterKey">;
export type EddsaPublicKey = Flavor<string, "EddsaPublicKey">;
export type EddsaPrivateKey = Flavor<string, "EddsaPrivateKey">;
/** /**
* Truth key, found in the recovery document. * Truth key, found in the recovery document.
*/ */
@ -53,6 +57,43 @@ export async function userIdentifierDerive(
return encodeCrock(result); return encodeCrock(result);
} }
export interface AccountKeyPair {
priv: EddsaPrivateKey;
pub: EddsaPublicKey;
}
export function accountKeypairDerive(userId: UserIdentifier): AccountKeyPair {
// FIXME: the KDF invocation looks fishy, but that's what the C code presently does.
const d = kdfKw({
outputLength: 32,
ikm: stringToBytes("ver"),
salt: decodeCrock(userId),
});
// FIXME: This bit twiddling seems wrong/unnecessary.
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
const pair = crypto_sign_keyPair_fromSeed(d);
return {
priv: encodeCrock(pair.secretKey),
pub: encodeCrock(pair.publicKey),
};
}
export async function encryptRecoveryDocument(
userId: UserIdentifier,
recoveryDoc: any,
): Promise<OpaqueData> {
const plaintext = stringToBytes(JSON.stringify(recoveryDoc));
const nonce = encodeCrock(getRandomBytes(nonceSize));
return anastasisEncrypt(
nonce,
asOpaque(userId),
encodeCrock(plaintext),
"erd",
);
}
function taConcat(chunks: Uint8Array[]): Uint8Array { function taConcat(chunks: Uint8Array[]): Uint8Array {
let payloadLen = 0; let payloadLen = 0;
for (const c of chunks) { for (const c of chunks) {

View File

@ -36,8 +36,10 @@ import {
} from "./reducer-types.js"; } from "./reducer-types.js";
import fetchPonyfill from "fetch-ponyfill"; import fetchPonyfill from "fetch-ponyfill";
import { import {
accountKeypairDerive,
coreSecretEncrypt, coreSecretEncrypt,
encryptKeyshare, encryptKeyshare,
encryptRecoveryDocument,
encryptTruth, encryptTruth,
PolicyKey, PolicyKey,
policyKeyDerive, policyKeyDerive,
@ -492,14 +494,25 @@ async function uploadSecret(
policies: policies.map((x, i) => { policies: policies.map((x, i) => {
return { return {
master_key: csr.encMasterKeys[i], master_key: csr.encMasterKeys[i],
// FIXME: ...
uuid: [], uuid: [],
salt: salt: undefined as any,
}; };
}), }),
}; };
for (const prov of state.policy_providers!) { for (const prov of state.policy_providers!) {
const uid = uidMap[prov.provider_url]
const acctKeypair = accountKeypairDerive(uid);
const encRecoveryDoc = await encryptRecoveryDocument(uid, rd);
// FIXME: Upload recovery document. // FIXME: Upload recovery document.
const resp = await fetch(
new URL(`policy/${acctKeypair.pub}`, prov.provider_url).href,
{
method: "POST",
body: decodeCrock(encRecoveryDoc),
},
);
} }
return { return {

View File

@ -22,4 +22,9 @@ export * from "./url.js";
export { fnutil } from "./fnutils.js"; export { fnutil } from "./fnutils.js";
export * from "./kdf.js"; export * from "./kdf.js";
export * from "./talerCrypto.js"; export * from "./talerCrypto.js";
export { randomBytes, secretbox, secretbox_open } from "./nacl-fast.js"; export {
randomBytes,
secretbox,
secretbox_open,
crypto_sign_keyPair_fromSeed,
} from "./nacl-fast.js";

View File

@ -59,15 +59,30 @@ export function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array {
return hmac(sha256, 64, key, message); return hmac(sha256, 64, key, message);
} }
/**
* HMAC-SHA512-SHA256 (see RFC 5869).
*/
export function kdfKw(args: {
outputLength: number;
ikm: Uint8Array;
salt?: Uint8Array;
info?: Uint8Array;
}) {
return kdf(args.outputLength, args.ikm, args.salt, args.info);
}
export function kdf( export function kdf(
outputLength: number, outputLength: number,
ikm: Uint8Array, ikm: Uint8Array,
salt: Uint8Array, salt?: Uint8Array,
info: Uint8Array, info?: Uint8Array,
): Uint8Array { ): Uint8Array {
salt = salt ?? new Uint8Array(64);
// extract // extract
const prk = hmacSha512(salt, ikm); const prk = hmacSha512(salt, ikm);
info = info ?? new Uint8Array(0);
// expand // expand
const N = Math.ceil(outputLength / 32); const N = Math.ceil(outputLength / 32);
const output = new Uint8Array(N * 32); const output = new Uint8Array(N * 32);

View File

@ -2894,7 +2894,6 @@ export function x25519_edwards_keyPair_fromSecretKey(
throw new Error("bad secret key size"); throw new Error("bad secret key size");
} }
d.set(secretKey, 0); d.set(secretKey, 0);
//crypto_hash(d, secretKey, 32);
d[0] &= 248; d[0] &= 248;
d[31] &= 127; d[31] &= 127;
@ -2906,7 +2905,7 @@ export function x25519_edwards_keyPair_fromSecretKey(
return pk; return pk;
} }
export function sign_keyPair_fromSecretKey( export function crypto_sign_keyPair_fromSecretKey(
secretKey: Uint8Array, secretKey: Uint8Array,
): { ): {
publicKey: Uint8Array; publicKey: Uint8Array;
@ -2920,7 +2919,7 @@ export function sign_keyPair_fromSecretKey(
return { publicKey: pk, secretKey: new Uint8Array(secretKey) }; return { publicKey: pk, secretKey: new Uint8Array(secretKey) };
} }
export function sign_keyPair_fromSeed( export function crypto_sign_keyPair_fromSeed(
seed: Uint8Array, seed: Uint8Array,
): { ): {
publicKey: Uint8Array; publicKey: Uint8Array;

View File

@ -69,7 +69,7 @@ test("taler-exchange-tvg eddsa key", (t) => {
const priv = "9TM70AKDTS57AWY9JK2J4TMBTMW6K62WHHGZWYDG0VM5ABPZKD40"; const priv = "9TM70AKDTS57AWY9JK2J4TMBTMW6K62WHHGZWYDG0VM5ABPZKD40";
const pub = "8GSJZ649T2PXMKZC01Y4ANNBE7MF14QVK9SQEC4E46ZHKCVG8AS0"; const pub = "8GSJZ649T2PXMKZC01Y4ANNBE7MF14QVK9SQEC4E46ZHKCVG8AS0";
const pair = nacl.sign_keyPair_fromSeed(decodeCrock(priv)); const pair = nacl.crypto_sign_keyPair_fromSeed(decodeCrock(priv));
t.deepEqual(encodeCrock(pair.publicKey), pub); t.deepEqual(encodeCrock(pair.publicKey), pub);
}); });

View File

@ -126,7 +126,7 @@ export function decodeCrock(encoded: string): Uint8Array {
} }
export function eddsaGetPublic(eddsaPriv: Uint8Array): Uint8Array { export function eddsaGetPublic(eddsaPriv: Uint8Array): Uint8Array {
const pair = nacl.sign_keyPair_fromSeed(eddsaPriv); const pair = nacl.crypto_sign_keyPair_fromSeed(eddsaPriv);
return pair.publicKey; return pair.publicKey;
} }
@ -353,7 +353,7 @@ export function hash(d: Uint8Array): Uint8Array {
} }
export function eddsaSign(msg: Uint8Array, eddsaPriv: Uint8Array): Uint8Array { export function eddsaSign(msg: Uint8Array, eddsaPriv: Uint8Array): Uint8Array {
const pair = nacl.sign_keyPair_fromSeed(eddsaPriv); const pair = nacl.crypto_sign_keyPair_fromSeed(eddsaPriv);
return nacl.sign_detached(msg, pair.secretKey); return nacl.sign_detached(msg, pair.secretKey);
} }
@ -447,3 +447,56 @@ export function setupRefreshTransferPub(
ecdhePub: ecdheGetPublic(out), ecdhePub: ecdheGetPublic(out),
}; };
} }
export enum TalerSignaturePurpose {
MERCHANT_TRACK_TRANSACTION = 1103,
WALLET_RESERVE_WITHDRAW = 1200,
WALLET_COIN_DEPOSIT = 1201,
MASTER_DENOMINATION_KEY_VALIDITY = 1025,
MASTER_WIRE_FEES = 1028,
MASTER_WIRE_DETAILS = 1030,
WALLET_COIN_MELT = 1202,
TEST = 4242,
MERCHANT_PAYMENT_OK = 1104,
MERCHANT_CONTRACT = 1101,
WALLET_COIN_RECOUP = 1203,
WALLET_COIN_LINK = 1204,
EXCHANGE_CONFIRM_RECOUP = 1039,
EXCHANGE_CONFIRM_RECOUP_REFRESH = 1041,
ANASTASIS_POLICY_UPLOAD = 1400,
ANASTASIS_POLICY_DOWNLOAD = 1401,
SYNC_BACKUP_UPLOAD = 1450,
}
export class SignaturePurposeBuilder {
private chunks: Uint8Array[] = [];
constructor(private purposeNum: number) {}
put(bytes: Uint8Array): SignaturePurposeBuilder {
this.chunks.push(Uint8Array.from(bytes));
return this;
}
build(): Uint8Array {
let payloadLen = 0;
for (const c of this.chunks) {
payloadLen += c.byteLength;
}
const buf = new ArrayBuffer(4 + 4 + payloadLen);
const u8buf = new Uint8Array(buf);
let p = 8;
for (const c of this.chunks) {
u8buf.set(c, p);
p += c.byteLength;
}
const dvbuf = new DataView(buf);
dvbuf.setUint32(0, payloadLen + 4 + 4);
dvbuf.setUint32(4, this.purposeNum);
return u8buf;
}
}
export function buildSigPS(purposeNum: number): SignaturePurposeBuilder {
return new SignaturePurposeBuilder(purposeNum);
}

View File

@ -34,7 +34,14 @@ import {
CoinSourceType, CoinSourceType,
} from "../../db.js"; } from "../../db.js";
import { CoinDepositPermission, RecoupRequest, RefreshPlanchetInfo } from "@gnu-taler/taler-util"; import {
buildSigPS,
CoinDepositPermission,
RecoupRequest,
RefreshPlanchetInfo,
SignaturePurposeBuilder,
TalerSignaturePurpose,
} from "@gnu-taler/taler-util";
// FIXME: These types should be internal to the wallet! // FIXME: These types should be internal to the wallet!
import { import {
BenchmarkResult, BenchmarkResult,
@ -80,24 +87,6 @@ import bigint from "big-integer";
const logger = new Logger("cryptoImplementation.ts"); const logger = new Logger("cryptoImplementation.ts");
enum SignaturePurpose {
MERCHANT_TRACK_TRANSACTION = 1103,
WALLET_RESERVE_WITHDRAW = 1200,
WALLET_COIN_DEPOSIT = 1201,
MASTER_DENOMINATION_KEY_VALIDITY = 1025,
MASTER_WIRE_FEES = 1028,
MASTER_WIRE_DETAILS = 1030,
WALLET_COIN_MELT = 1202,
TEST = 4242,
MERCHANT_PAYMENT_OK = 1104,
MERCHANT_CONTRACT = 1101,
WALLET_COIN_RECOUP = 1203,
WALLET_COIN_LINK = 1204,
EXCHANGE_CONFIRM_RECOUP = 1039,
EXCHANGE_CONFIRM_RECOUP_REFRESH = 1041,
SYNC_BACKUP_UPLOAD = 1450,
}
function amountToBuffer(amount: AmountJson): Uint8Array { function amountToBuffer(amount: AmountJson): Uint8Array {
const buffer = new ArrayBuffer(8 + 4 + 12); const buffer = new ArrayBuffer(8 + 4 + 12);
const dvbuf = new DataView(buffer); const dvbuf = new DataView(buffer);
@ -139,38 +128,6 @@ function timestampRoundedToBuffer(ts: Timestamp): Uint8Array {
return new Uint8Array(b); return new Uint8Array(b);
} }
class SignaturePurposeBuilder {
private chunks: Uint8Array[] = [];
constructor(private purposeNum: number) { }
put(bytes: Uint8Array): SignaturePurposeBuilder {
this.chunks.push(Uint8Array.from(bytes));
return this;
}
build(): Uint8Array {
let payloadLen = 0;
for (const c of this.chunks) {
payloadLen += c.byteLength;
}
const buf = new ArrayBuffer(4 + 4 + payloadLen);
const u8buf = new Uint8Array(buf);
let p = 8;
for (const c of this.chunks) {
u8buf.set(c, p);
p += c.byteLength;
}
const dvbuf = new DataView(buf);
dvbuf.setUint32(0, payloadLen + 4 + 4);
dvbuf.setUint32(4, this.purposeNum);
return u8buf;
}
}
function buildSigPS(purposeNum: number): SignaturePurposeBuilder {
return new SignaturePurposeBuilder(purposeNum);
}
export class CryptoImplementation { export class CryptoImplementation {
static enableTracing = false; static enableTracing = false;
@ -192,7 +149,9 @@ export class CryptoImplementation {
const denomPubHash = hash(denomPub); const denomPubHash = hash(denomPub);
const evHash = hash(ev); const evHash = hash(ev);
const withdrawRequest = buildSigPS(SignaturePurpose.WALLET_RESERVE_WITHDRAW) const withdrawRequest = buildSigPS(
TalerSignaturePurpose.WALLET_RESERVE_WITHDRAW,
)
.put(reservePub) .put(reservePub)
.put(amountToBuffer(amountWithFee)) .put(amountToBuffer(amountWithFee))
.put(denomPubHash) .put(denomPubHash)
@ -236,7 +195,7 @@ export class CryptoImplementation {
} }
signTrackTransaction(req: SignTrackTransactionRequest): string { signTrackTransaction(req: SignTrackTransactionRequest): string {
const p = buildSigPS(SignaturePurpose.MERCHANT_TRACK_TRANSACTION) const p = buildSigPS(TalerSignaturePurpose.MERCHANT_TRACK_TRANSACTION)
.put(decodeCrock(req.contractTermsHash)) .put(decodeCrock(req.contractTermsHash))
.put(decodeCrock(req.wireHash)) .put(decodeCrock(req.wireHash))
.put(decodeCrock(req.merchantPub)) .put(decodeCrock(req.merchantPub))
@ -249,7 +208,7 @@ export class CryptoImplementation {
* Create and sign a message to recoup a coin. * Create and sign a message to recoup a coin.
*/ */
createRecoupRequest(coin: CoinRecord): RecoupRequest { createRecoupRequest(coin: CoinRecord): RecoupRequest {
const p = buildSigPS(SignaturePurpose.WALLET_COIN_RECOUP) const p = buildSigPS(TalerSignaturePurpose.WALLET_COIN_RECOUP)
.put(decodeCrock(coin.coinPub)) .put(decodeCrock(coin.coinPub))
.put(decodeCrock(coin.denomPubHash)) .put(decodeCrock(coin.denomPubHash))
.put(decodeCrock(coin.blindingKey)) .put(decodeCrock(coin.blindingKey))
@ -276,7 +235,7 @@ export class CryptoImplementation {
contractHash: string, contractHash: string,
merchantPub: string, merchantPub: string,
): boolean { ): boolean {
const p = buildSigPS(SignaturePurpose.MERCHANT_PAYMENT_OK) const p = buildSigPS(TalerSignaturePurpose.MERCHANT_PAYMENT_OK)
.put(decodeCrock(contractHash)) .put(decodeCrock(contractHash))
.build(); .build();
const sigBytes = decodeCrock(sig); const sigBytes = decodeCrock(sig);
@ -288,7 +247,7 @@ export class CryptoImplementation {
* Check if a wire fee is correctly signed. * Check if a wire fee is correctly signed.
*/ */
isValidWireFee(type: string, wf: WireFee, masterPub: string): boolean { isValidWireFee(type: string, wf: WireFee, masterPub: string): boolean {
const p = buildSigPS(SignaturePurpose.MASTER_WIRE_FEES) const p = buildSigPS(TalerSignaturePurpose.MASTER_WIRE_FEES)
.put(hash(stringToBytes(type + "\0"))) .put(hash(stringToBytes(type + "\0")))
.put(timestampRoundedToBuffer(wf.startStamp)) .put(timestampRoundedToBuffer(wf.startStamp))
.put(timestampRoundedToBuffer(wf.endStamp)) .put(timestampRoundedToBuffer(wf.endStamp))
@ -304,7 +263,7 @@ export class CryptoImplementation {
* Check if the signature of a denomination is valid. * Check if the signature of a denomination is valid.
*/ */
isValidDenom(denom: DenominationRecord, masterPub: string): boolean { isValidDenom(denom: DenominationRecord, masterPub: string): boolean {
const p = buildSigPS(SignaturePurpose.MASTER_DENOMINATION_KEY_VALIDITY) const p = buildSigPS(TalerSignaturePurpose.MASTER_DENOMINATION_KEY_VALIDITY)
.put(decodeCrock(masterPub)) .put(decodeCrock(masterPub))
.put(timestampRoundedToBuffer(denom.stampStart)) .put(timestampRoundedToBuffer(denom.stampStart))
.put(timestampRoundedToBuffer(denom.stampExpireWithdraw)) .put(timestampRoundedToBuffer(denom.stampExpireWithdraw))
@ -334,7 +293,9 @@ export class CryptoImplementation {
stringToBytes(paytoUri + "\0"), stringToBytes(paytoUri + "\0"),
new Uint8Array(0), new Uint8Array(0),
); );
const p = buildSigPS(SignaturePurpose.MASTER_WIRE_DETAILS).put(h).build(); const p = buildSigPS(TalerSignaturePurpose.MASTER_WIRE_DETAILS)
.put(h)
.build();
return eddsaVerify(p, decodeCrock(sig), decodeCrock(masterPub)); return eddsaVerify(p, decodeCrock(sig), decodeCrock(masterPub));
} }
@ -344,7 +305,7 @@ export class CryptoImplementation {
merchantPub: string, merchantPub: string,
): boolean { ): boolean {
const cthDec = decodeCrock(contractTermsHash); const cthDec = decodeCrock(contractTermsHash);
const p = buildSigPS(SignaturePurpose.MERCHANT_CONTRACT) const p = buildSigPS(TalerSignaturePurpose.MERCHANT_CONTRACT)
.put(cthDec) .put(cthDec)
.build(); .build();
return eddsaVerify(p, decodeCrock(sig), decodeCrock(merchantPub)); return eddsaVerify(p, decodeCrock(sig), decodeCrock(merchantPub));
@ -364,8 +325,8 @@ export class CryptoImplementation {
eddsaGetPublic(key: string): { priv: string; pub: string } { eddsaGetPublic(key: string): { priv: string; pub: string } {
return { return {
priv: key, priv: key,
pub: encodeCrock(eddsaGetPublic(decodeCrock(key))) pub: encodeCrock(eddsaGetPublic(decodeCrock(key))),
} };
} }
/** /**
@ -392,7 +353,7 @@ export class CryptoImplementation {
* and deposit permissions for each given coin. * and deposit permissions for each given coin.
*/ */
signDepositPermission(depositInfo: DepositInfo): CoinDepositPermission { signDepositPermission(depositInfo: DepositInfo): CoinDepositPermission {
const d = buildSigPS(SignaturePurpose.WALLET_COIN_DEPOSIT) const d = buildSigPS(TalerSignaturePurpose.WALLET_COIN_DEPOSIT)
.put(decodeCrock(depositInfo.contractTermsHash)) .put(decodeCrock(depositInfo.contractTermsHash))
.put(decodeCrock(depositInfo.wireInfoHash)) .put(decodeCrock(depositInfo.wireInfoHash))
.put(decodeCrock(depositInfo.denomPubHash)) .put(decodeCrock(depositInfo.denomPubHash))
@ -503,7 +464,7 @@ export class CryptoImplementation {
} }
const sessionHash = sessionHc.finish(); const sessionHash = sessionHc.finish();
const confirmData = buildSigPS(SignaturePurpose.WALLET_COIN_MELT) const confirmData = buildSigPS(TalerSignaturePurpose.WALLET_COIN_MELT)
.put(sessionHash) .put(sessionHash)
.put(decodeCrock(meltCoinDenomPubHash)) .put(decodeCrock(meltCoinDenomPubHash))
.put(amountToBuffer(valueWithFee)) .put(amountToBuffer(valueWithFee))
@ -549,7 +510,7 @@ export class CryptoImplementation {
coinEv: string, coinEv: string,
): string { ): string {
const coinEvHash = hash(decodeCrock(coinEv)); const coinEvHash = hash(decodeCrock(coinEv));
const coinLink = buildSigPS(SignaturePurpose.WALLET_COIN_LINK) const coinLink = buildSigPS(TalerSignaturePurpose.WALLET_COIN_LINK)
.put(decodeCrock(newDenomHash)) .put(decodeCrock(newDenomHash))
.put(decodeCrock(transferPub)) .put(decodeCrock(transferPub))
.put(coinEvHash) .put(coinEvHash)
@ -622,9 +583,7 @@ export class CryptoImplementation {
} else { } else {
hOld = new Uint8Array(64); hOld = new Uint8Array(64);
} }
const sigBlob = new SignaturePurposeBuilder( const sigBlob = buildSigPS(TalerSignaturePurpose.SYNC_BACKUP_UPLOAD)
SignaturePurpose.SYNC_BACKUP_UPLOAD,
)
.put(hOld) .put(hOld)
.put(hNew) .put(hNew)
.build(); .build();

View File

@ -763,6 +763,8 @@ async function processDownloadProposalImpl(
proposalResp.contract_terms, proposalResp.contract_terms,
); );
logger.info(`Contract terms hash: ${contractTermsHash}`);
let parsedContractTerms: ContractTerms; let parsedContractTerms: ContractTerms;
try { try {

View File

@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/ */
import { canonicalJson } from "@gnu-taler/taler-util"; import { canonicalJson, Logger } from "@gnu-taler/taler-util";
import { kdf } from "@gnu-taler/taler-util"; import { kdf } from "@gnu-taler/taler-util";
import { import {
decodeCrock, decodeCrock,
@ -24,6 +24,8 @@ import {
stringToBytes, stringToBytes,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
const logger = new Logger("contractTerms.ts");
export namespace ContractTermsUtil { export namespace ContractTermsUtil {
export type PathPredicate = (path: string[]) => boolean; export type PathPredicate = (path: string[]) => boolean;
@ -222,6 +224,8 @@ export namespace ContractTermsUtil {
export function hashContractTerms(contractTerms: unknown): string { export function hashContractTerms(contractTerms: unknown): string {
const cleaned = scrub(contractTerms); const cleaned = scrub(contractTerms);
const canon = canonicalJson(cleaned) + "\0"; const canon = canonicalJson(cleaned) + "\0";
return encodeCrock(hash(stringToBytes(canon))); const bytes = stringToBytes(canon);
logger.info(`contract terms before hashing: ${encodeCrock(bytes)}`);
return encodeCrock(hash(bytes));
} }
} }

View File

@ -16,11 +16,15 @@ importers:
specifiers: specifiers:
'@gnu-taler/taler-util': workspace:^0.8.3 '@gnu-taler/taler-util': workspace:^0.8.3
ava: ^3.15.0 ava: ^3.15.0
fetch-ponyfill: ^7.1.0
hash-wasm: ^4.9.0 hash-wasm: ^4.9.0
node-fetch: ^3.0.0
typescript: ^4.4.3 typescript: ^4.4.3
dependencies: dependencies:
'@gnu-taler/taler-util': link:../taler-util '@gnu-taler/taler-util': link:../taler-util
fetch-ponyfill: 7.1.0
hash-wasm: 4.9.0 hash-wasm: 4.9.0
node-fetch: 3.0.0
devDependencies: devDependencies:
ava: 3.15.0 ava: 3.15.0
typescript: 4.4.3 typescript: 4.4.3
@ -32,6 +36,7 @@ importers:
'@types/jest': ^26.0.8 '@types/jest': ^26.0.8
'@typescript-eslint/eslint-plugin': ^2.25.0 '@typescript-eslint/eslint-plugin': ^2.25.0
'@typescript-eslint/parser': ^2.25.0 '@typescript-eslint/parser': ^2.25.0
anastasis-core: workspace:^0.0.1
enzyme: ^3.11.0 enzyme: ^3.11.0
enzyme-adapter-preact-pure: ^3.1.0 enzyme-adapter-preact-pure: ^3.1.0
eslint: ^6.8.0 eslint: ^6.8.0
@ -46,6 +51,7 @@ importers:
typescript: ^3.7.5 typescript: ^3.7.5
dependencies: dependencies:
'@gnu-taler/taler-util': link:../taler-util '@gnu-taler/taler-util': link:../taler-util
anastasis-core: link:../anastasis-core
preact: 10.5.14 preact: 10.5.14
preact-render-to-string: 5.1.19_preact@10.5.14 preact-render-to-string: 5.1.19_preact@10.5.14
preact-router: 3.2.1_preact@10.5.14 preact-router: 3.2.1_preact@10.5.14
@ -9701,6 +9707,11 @@ packages:
assert-plus: 1.0.0 assert-plus: 1.0.0
dev: true dev: true
/data-uri-to-buffer/3.0.1:
resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==}
engines: {node: '>= 6'}
dev: false
/data-urls/1.1.0: /data-urls/1.1.0:
resolution: {integrity: sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==} resolution: {integrity: sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==}
dependencies: dependencies:
@ -11267,6 +11278,19 @@ packages:
bser: 2.1.1 bser: 2.1.1
dev: true dev: true
/fetch-blob/3.1.2:
resolution: {integrity: sha512-hunJbvy/6OLjCD0uuhLdp0mMPzP/yd2ssd1t2FCJsaA7wkWhpbp9xfuNVpv7Ll4jFhzp6T4LAupSiV9uOeg0VQ==}
engines: {node: ^12.20 || >= 14.13}
dependencies:
web-streams-polyfill: 3.1.1
dev: false
/fetch-ponyfill/7.1.0:
resolution: {integrity: sha512-FhbbL55dj/qdVO3YNK7ZEkshvj3eQ7EuIGV2I6ic/2YiocvyWv+7jg2s4AyS0wdRU75s3tA8ZxI/xPigb0v5Aw==}
dependencies:
node-fetch: 2.6.1
dev: false
/fflate/0.6.0: /fflate/0.6.0:
resolution: {integrity: sha512-u4AdW/Xx7iinDhYQuS0B0vvbUX7JWXO07jEvYUlbNZvtoiDLkDvHR17LSwxhbawjZVDXczzLHAQUDSllISm4/A==} resolution: {integrity: sha512-u4AdW/Xx7iinDhYQuS0B0vvbUX7JWXO07jEvYUlbNZvtoiDLkDvHR17LSwxhbawjZVDXczzLHAQUDSllISm4/A==}
dev: false dev: false
@ -11658,6 +11682,7 @@ packages:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin] os: [darwin]
requiresBuild: true
dev: true dev: true
optional: true optional: true
@ -15032,7 +15057,14 @@ packages:
/node-fetch/2.6.1: /node-fetch/2.6.1:
resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==} resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==}
engines: {node: 4.x || >=6.0.0} engines: {node: 4.x || >=6.0.0}
dev: true
/node-fetch/3.0.0:
resolution: {integrity: sha512-bKMI+C7/T/SPU1lKnbQbwxptpCrG9ashG+VkytmXCPZyuM9jB6VU+hY0oi4lC8LxTtAeWdckNCTa3nrGsAdA3Q==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
data-uri-to-buffer: 3.0.1
fetch-blob: 3.1.2
dev: false
/node-forge/0.10.0: /node-forge/0.10.0:
resolution: {integrity: sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==} resolution: {integrity: sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==}
@ -20331,6 +20363,11 @@ packages:
resolution: {integrity: sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==} resolution: {integrity: sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==}
dev: true dev: true
/web-streams-polyfill/3.1.1:
resolution: {integrity: sha512-Czi3fG883e96T4DLEPRvufrF2ydhOOW1+1a6c3gNjH2aIh50DNFBdfwh2AKoOf1rXvpvavAoA11Qdq9+BKjE0Q==}
engines: {node: '>= 8'}
dev: false
/webidl-conversions/4.0.2: /webidl-conversions/4.0.2:
resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
dev: true dev: true