taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 0aa8254d84d35ed8945724153340c036ceaf6e76
parent afc4cd9ed32e75d309daa68013694c9c0c65996b
Author: Florian Dold <dold@taler.net>
Date:   Wed, 22 Jul 2026 20:44:08 +0200

util: test the donation unit codec against the donau's format

Covers a unit exactly as the donau packs it, the cases that have to be
rejected, and that the key hash follows from the key alone.

Diffstat:
Apackages/taler-util/src/types-donau.test.ts | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 106 insertions(+), 0 deletions(-)

diff --git a/packages/taler-util/src/types-donau.test.ts b/packages/taler-util/src/types-donau.test.ts @@ -0,0 +1,106 @@ +/* + This file is part of GNU Taler + (C) 2026 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import assert from "node:assert"; +import { test } from "node:test"; +import { encodeCrock, hash, stringToBytes } from "./taler-crypto.js"; +import { + codecForDonationUnitKeyGroup, + hashDonationUnitPub, +} from "./types-donau.js"; + +/** + * One donation unit exactly as the donau sends it, i.e. the cipher and the key + * and nothing else. Taken from the packing in + * donau/src/donau/donau-httpd_get-keys.c. + */ +const wireGroup = { + donation_unit_pub: { + cipher: "RSA", + rsa_public_key: "040000W1", + }, + year: 2026, + lost: false, + value: "TESTKUDOS:0.01", +}; + +test("a donation unit as the donau sends it decodes", (t) => { + const res = codecForDonationUnitKeyGroup().decode(wireGroup); + assert.deepStrictEqual(res, { + donation_unit_pub: { + cipher: "RSA", + rsa_public_key: "040000W1", + }, + value: "TESTKUDOS:0.01", + year: 2026, + lost: false, + }); +}); + +test("a donation unit missing its key is rejected", (t) => { + const cases: [string, unknown][] = [ + ["no donation_unit_pub", { year: 2026, value: "TESTKUDOS:1" }], + [ + "unknown cipher", + { ...wireGroup, donation_unit_pub: { cipher: "XYZ", key: "x" } }, + ], + [ + "RSA without the key", + { ...wireGroup, donation_unit_pub: { cipher: "RSA" } }, + ], + [ + "CS without the key", + { ...wireGroup, donation_unit_pub: { cipher: "CS" } }, + ], + ["year is not a number", { ...wireGroup, year: "2026" }], + ["value is not an amount", { ...wireGroup, value: "nope" }], + ]; + for (const [name, v] of cases) { + assert.throws( + () => codecForDonationUnitKeyGroup().decode(v), + `${name} must be rejected`, + ); + } +}); + +test("the CS variant carries the key under the name the donau uses", (t) => { + const res = codecForDonationUnitKeyGroup().decode({ + ...wireGroup, + donation_unit_pub: { cipher: "CS", cs_public_key: "0123456789ABCDEG" }, + }); + assert.deepStrictEqual(res.donation_unit_pub, { + cipher: "CS", + cs_public_key: "0123456789ABCDEG", + }); +}); + +test("the donation unit hash is taken over the encoded key", (t) => { + // The donau hashes the encoded key, which is what the wire carries, so the + // hash has to come out of the key alone. + const key = encodeCrock(stringToBytes("donation-unit-key")); + assert.strictEqual( + hashDonationUnitPub({ cipher: "RSA", rsa_public_key: key }), + encodeCrock(hash(stringToBytes("donation-unit-key"))), + ); + // A different key gives a different hash. + const other = encodeCrock(stringToBytes("another-key")); + assert.notStrictEqual( + hashDonationUnitPub({ cipher: "RSA", rsa_public_key: other }), + hashDonationUnitPub({ cipher: "RSA", rsa_public_key: key }), + ); +});