always round timestamps before signature creation/verification
This commit is contained in:
parent
faba5e9db8
commit
34eca9c512
@ -64,7 +64,7 @@ import {
|
|||||||
} from "../talerCrypto";
|
} from "../talerCrypto";
|
||||||
import { randomBytes } from "../primitives/nacl-fast";
|
import { randomBytes } from "../primitives/nacl-fast";
|
||||||
import { kdf } from "../primitives/kdf";
|
import { kdf } from "../primitives/kdf";
|
||||||
import { Timestamp, getTimestampNow } from "../../util/time";
|
import { Timestamp, getTimestampNow, timestampTruncateToSecond } from "../../util/time";
|
||||||
|
|
||||||
enum SignaturePurpose {
|
enum SignaturePurpose {
|
||||||
RESERVE_WITHDRAW = 1200,
|
RESERVE_WITHDRAW = 1200,
|
||||||
@ -94,13 +94,15 @@ function amountToBuffer(amount: AmountJson): Uint8Array {
|
|||||||
return u8buf;
|
return u8buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
function timestampToBuffer(ts: Timestamp): Uint8Array {
|
function timestampRoundedToBuffer(ts: Timestamp): Uint8Array {
|
||||||
const b = new ArrayBuffer(8);
|
const b = new ArrayBuffer(8);
|
||||||
const v = new DataView(b);
|
const v = new DataView(b);
|
||||||
const s = BigInt(ts.t_ms) * BigInt(1000);
|
const tsRounded = timestampTruncateToSecond(ts);
|
||||||
|
const s = BigInt(tsRounded.t_ms) * BigInt(1000);
|
||||||
v.setBigUint64(0, s);
|
v.setBigUint64(0, s);
|
||||||
return new Uint8Array(b);
|
return new Uint8Array(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignaturePurposeBuilder {
|
class SignaturePurposeBuilder {
|
||||||
private chunks: Uint8Array[] = [];
|
private chunks: Uint8Array[] = [];
|
||||||
|
|
||||||
@ -245,8 +247,8 @@ export class CryptoImplementation {
|
|||||||
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(SignaturePurpose.MASTER_WIRE_FEES)
|
||||||
.put(hash(stringToBytes(type + "\0")))
|
.put(hash(stringToBytes(type + "\0")))
|
||||||
.put(timestampToBuffer(wf.startStamp))
|
.put(timestampRoundedToBuffer(wf.startStamp))
|
||||||
.put(timestampToBuffer(wf.endStamp))
|
.put(timestampRoundedToBuffer(wf.endStamp))
|
||||||
.put(amountToBuffer(wf.wireFee))
|
.put(amountToBuffer(wf.wireFee))
|
||||||
.put(amountToBuffer(wf.closingFee))
|
.put(amountToBuffer(wf.closingFee))
|
||||||
.build();
|
.build();
|
||||||
@ -261,10 +263,10 @@ export class CryptoImplementation {
|
|||||||
isValidDenom(denom: DenominationRecord, masterPub: string): boolean {
|
isValidDenom(denom: DenominationRecord, masterPub: string): boolean {
|
||||||
const p = buildSigPS(SignaturePurpose.MASTER_DENOMINATION_KEY_VALIDITY)
|
const p = buildSigPS(SignaturePurpose.MASTER_DENOMINATION_KEY_VALIDITY)
|
||||||
.put(decodeCrock(masterPub))
|
.put(decodeCrock(masterPub))
|
||||||
.put(timestampToBuffer(denom.stampStart))
|
.put(timestampRoundedToBuffer(denom.stampStart))
|
||||||
.put(timestampToBuffer(denom.stampExpireWithdraw))
|
.put(timestampRoundedToBuffer(denom.stampExpireWithdraw))
|
||||||
.put(timestampToBuffer(denom.stampExpireDeposit))
|
.put(timestampRoundedToBuffer(denom.stampExpireDeposit))
|
||||||
.put(timestampToBuffer(denom.stampExpireLegal))
|
.put(timestampRoundedToBuffer(denom.stampExpireLegal))
|
||||||
.put(amountToBuffer(denom.value))
|
.put(amountToBuffer(denom.value))
|
||||||
.put(amountToBuffer(denom.feeWithdraw))
|
.put(amountToBuffer(denom.feeWithdraw))
|
||||||
.put(amountToBuffer(denom.feeDeposit))
|
.put(amountToBuffer(denom.feeDeposit))
|
||||||
@ -330,8 +332,8 @@ export class CryptoImplementation {
|
|||||||
const d = buildSigPS(SignaturePurpose.WALLET_COIN_DEPOSIT)
|
const d = buildSigPS(SignaturePurpose.WALLET_COIN_DEPOSIT)
|
||||||
.put(decodeCrock(depositInfo.contractTermsHash))
|
.put(decodeCrock(depositInfo.contractTermsHash))
|
||||||
.put(decodeCrock(depositInfo.wireInfoHash))
|
.put(decodeCrock(depositInfo.wireInfoHash))
|
||||||
.put(timestampToBuffer(depositInfo.timestamp))
|
.put(timestampRoundedToBuffer(depositInfo.timestamp))
|
||||||
.put(timestampToBuffer(depositInfo.refundDeadline))
|
.put(timestampRoundedToBuffer(depositInfo.refundDeadline))
|
||||||
.put(amountToBuffer(depositInfo.spendAmount))
|
.put(amountToBuffer(depositInfo.spendAmount))
|
||||||
.put(amountToBuffer(depositInfo.feeDeposit))
|
.put(amountToBuffer(depositInfo.feeDeposit))
|
||||||
.put(decodeCrock(depositInfo.merchantPub))
|
.put(decodeCrock(depositInfo.merchantPub))
|
||||||
|
@ -49,6 +49,7 @@ export function getTimestampNow(): Timestamp {
|
|||||||
export function getDurationRemaining(
|
export function getDurationRemaining(
|
||||||
deadline: Timestamp,
|
deadline: Timestamp,
|
||||||
now = getTimestampNow(),
|
now = getTimestampNow(),
|
||||||
|
|
||||||
): Duration {
|
): Duration {
|
||||||
if (deadline.t_ms === "never") {
|
if (deadline.t_ms === "never") {
|
||||||
return { d_ms: "forever" };
|
return { d_ms: "forever" };
|
||||||
@ -72,6 +73,19 @@ export function timestampMin(t1: Timestamp, t2: Timestamp): Timestamp {
|
|||||||
return { t_ms: Math.min(t1.t_ms, t2.t_ms) };
|
return { t_ms: Math.min(t1.t_ms, t2.t_ms) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Truncate a timestamp so that that it represents a multiple
|
||||||
|
* of seconds. The timestamp is always rounded down.
|
||||||
|
*/
|
||||||
|
export function timestampTruncateToSecond(t1: Timestamp): Timestamp {
|
||||||
|
if (t1.t_ms === "never") {
|
||||||
|
return { t_ms: "never" };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
t_ms: Math.floor(t1.t_ms / 1000) * 1000,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function durationMin(d1: Duration, d2: Duration): Duration {
|
export function durationMin(d1: Duration, d2: Duration): Duration {
|
||||||
if (d1.d_ms === "forever") {
|
if (d1.d_ms === "forever") {
|
||||||
return { d_ms: d2.d_ms };
|
return { d_ms: d2.d_ms };
|
||||||
|
Loading…
Reference in New Issue
Block a user