validate wire fees and acct info

This commit is contained in:
Florian Dold 2019-12-05 23:07:46 +01:00
parent 8115ac660c
commit 7b54439fd6
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
3 changed files with 59 additions and 10 deletions

View File

@ -409,6 +409,10 @@ export class CryptoApi {
return this.doRpc<boolean>("rsaVerify", 4, hm, sig, pk);
}
isValidWireAccount(paytoUri: string, sig: string, masterPub: string): Promise<boolean> {
return this.doRpc<boolean>("isValidWireAccount", 4, paytoUri, sig, masterPub);
}
createPaybackRequest(coin: CoinRecord): Promise<PaybackRequest> {
return this.doRpc<PaybackRequest>("createPaybackRequest", 1, coin);
}

View File

@ -68,15 +68,17 @@ import {
rsaVerify,
} from "../talerCrypto";
import { randomBytes } from "../primitives/nacl-fast";
import { kdf } from "../primitives/kdf";
enum SignaturePurpose {
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,
MASTER_WIRE_FEES = 1028,
WALLET_COIN_PAYBACK = 1203,
WALLET_COIN_LINK = 1204,
}
@ -157,9 +159,7 @@ export class CryptoImplementation {
* Create a pre-coin of the given denomination to be withdrawn from then given
* reserve.
*/
createPlanchet(
req: PlanchetCreationRequest,
): PlanchetCreationResult {
createPlanchet(req: PlanchetCreationRequest): PlanchetCreationResult {
const reservePub = decodeCrock(req.reservePub);
const reservePriv = decodeCrock(req.reservePriv);
const denomPub = decodeCrock(req.denomPub);
@ -264,6 +264,7 @@ export class CryptoImplementation {
.put(timestampToBuffer(wf.startStamp))
.put(timestampToBuffer(wf.endStamp))
.put(amountToBuffer(wf.wireFee))
.put(amountToBuffer(wf.closingFee))
.build();
const sig = decodeCrock(wf.sig);
const pub = decodeCrock(masterPub);
@ -292,6 +293,23 @@ export class CryptoImplementation {
return eddsaVerify(p, sig, pub);
}
isValidWireAccount(
paytoUri: string,
sig: string,
masterPub: string,
): boolean {
const h = kdf(
64,
stringToBytes("exchange-wire-signature"),
stringToBytes(paytoUri + "\0"),
new Uint8Array(0),
);
const p = buildSigPS(SignaturePurpose.MASTER_WIRE_DETAILS)
.put(h)
.build();
return eddsaVerify(p, decodeCrock(sig), decodeCrock(masterPub));
}
/**
* Create a new EdDSA key pair.
*/

View File

@ -15,10 +15,13 @@
*/
import { InternalWalletState } from "./state";
import { WALLET_CACHE_BREAKER_CLIENT_VERSION } from "../wallet";
import {
WALLET_CACHE_BREAKER_CLIENT_VERSION,
} from "../wallet";
import { KeysJson, Denomination, ExchangeWireJson } from "../talerTypes";
KeysJson,
Denomination,
ExchangeWireJson,
WireFeesJson,
} from "../talerTypes";
import { getTimestampNow, OperationError } from "../walletTypes";
import {
ExchangeRecord,
@ -229,8 +232,12 @@ async function updateExchangeWithWireInfo(
if (exchange.updateStatus != ExchangeUpdateStatus.FETCH_WIRE) {
return;
}
const details = exchange.details;
if (!details) {
throw Error("invalid exchange state");
}
const reqUrl = new URL("wire", exchangeBaseUrl);
reqUrl.searchParams.set("cacheBreaker", WALLET_CACHE_BREAKER_CLIENT_VERSION)
reqUrl.searchParams.set("cacheBreaker", WALLET_CACHE_BREAKER_CLIENT_VERSION);
const resp = await ws.http.get(reqUrl.href);
@ -239,6 +246,17 @@ async function updateExchangeWithWireInfo(
throw Error("/wire response malformed");
}
const wireInfo = ExchangeWireJson.checked(wiJson);
for (const a of wireInfo.accounts) {
console.log("validating exchange acct");
const isValid = await ws.cryptoApi.isValidWireAccount(
a.url,
a.master_sig,
details.masterPublicKey,
);
if (!isValid) {
throw Error("exchange acct signature invalid");
}
}
const feesForType: { [wireMethod: string]: WireFee[] } = {};
for (const wireMethod of Object.keys(wireInfo.fees)) {
const feeList: WireFee[] = [];
@ -251,13 +269,22 @@ async function updateExchangeWithWireInfo(
if (!endStamp) {
throw Error("wrong date format");
}
feeList.push({
const fee: WireFee = {
closingFee: Amounts.parseOrThrow(x.closing_fee),
endStamp,
sig: x.sig,
startStamp,
wireFee: Amounts.parseOrThrow(x.wire_fee),
});
};
const isValid = await ws.cryptoApi.isValidWireFee(
wireMethod,
fee,
details.masterPublicKey,
);
if (!isValid) {
throw Error("exchange wire fee signature invalid");
}
feeList.push(fee);
}
feesForType[wireMethod] = feeList;
}