taler-typescript-core

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

commit 4002f124f2bfe26e5084012ed6d1cda56ddee37a
parent 9835654765454e1cdf3adb311d4c1ff878a8f21b
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Fri,  7 Nov 2025 21:23:39 +0100

minor refactoring

Diffstat:
Mpackages/taler-wallet-core/src/mailbox.ts | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 53 insertions(+), 26 deletions(-)

diff --git a/packages/taler-wallet-core/src/mailbox.ts b/packages/taler-wallet-core/src/mailbox.ts @@ -225,6 +225,27 @@ export async function initMailbox( return mailboxConf; } +function decryptTalerUriMessage( + sk: Uint8Array, + msg: Uint8Array, +) : string | undefined { + const header = new Uint8Array(msg.slice(0, 4)); + const ct = new Uint8Array(msg.slice(4)); + const uri = hpkeOpenOneshot(sk, + stringToBytes("mailbox-message"), + header, // AAD + ct); + if (!uri) { + return undefined; + } + // Find start of padding + const padIdx = uri.indexOf(0x00); + if (-1 === padIdx) { + return new TextDecoder().decode(uri); + } + return new TextDecoder().decode(uri.slice(0, padIdx)) +} + /** * Refresh mailbox through HTTP */ @@ -266,21 +287,16 @@ export async function refreshMailbox( const offset = i * message_size; const msg: Uint8Array = messages.slice(offset, offset + message_size); - const header = new Uint8Array(msg.slice(0, 4)); - const ct = new Uint8Array(msg.slice(4)); - const uri = hpkeOpenOneshot(hpkeSk, - stringToBytes("mailbox-message"), - header, // AAD - ct); + const uri = decryptTalerUriMessage(hpkeSk, + msg); if (!uri) { logger.warn(`unable to decrypt message number ${i}`); - continue; // FIXME log + continue; } // Find start of padding - const padIdx = uri.indexOf(0x00); const newMessage = { originMailboxBaseUrl: mailboxConf.mailboxBaseUrl, - talerUri: new TextDecoder().decode(uri.slice(0, padIdx)), + talerUri: uri, downloadedAt: now, }; records.push(newMessage); @@ -318,16 +334,38 @@ export async function refreshMailbox( } } +function encryptTalerUriMessage( + encryptionKey: Uint8Array, + talerUri: string, + paddedMessageSize: number +) : Uint8Array { + const headerBuf = new ArrayBuffer(4); + // Padding must not include HPKE tag and encapsulation overhead + // FIXME CRYPTO-AGILITY size of tag and encapsulation depends on used algos + // DHKEM X25519: Encapsuation 32 bytes, Poly1305 tag 16 bytes + const paddingLength = paddedMessageSize - 4 - talerUri.length - 16 - 32; + const v = new DataView(headerBuf); + v.setUint32(0, 0); // FIXME message type, derive number from crypto! + const header = new Uint8Array(headerBuf); + const padding = new Uint8Array(paddingLength).fill(0); + const msg = new Uint8Array([...stringToBytes(talerUri), ...padding]); + const encryptedMessage = hpkeSealOneshot(encryptionKey, + stringToBytes("mailbox-message"), + header, + msg); + return new Uint8Array([...header, ...encryptedMessage]) +} + export async function sendTalerUriMessage( wex: WalletExecutionContext, req: SendTalerUriMailboxMessageRequest) : Promise<EmptyObject> { const mailboxClient = new TalerMailboxInstanceHttpClient(req.contact.mailboxBaseUri, wex.http); // Get message size - var message_size; + var paddedMessageSize; const resConf = await mailboxClient.getConfig(); switch (resConf.case) { case "ok": - message_size = resConf.body.message_body_bytes; + paddedMessageSize = resConf.body.message_body_bytes; break; default: return {}; @@ -341,23 +379,12 @@ export async function sendTalerUriMessage( default: throw Error("unable to get mailbox keys"); } - const headerBuf = new ArrayBuffer(4); - // Padding must not include HPKE tag and encapsulation overhead - // FIXME CRYPTO-AGILITY size of tag and encapsulation depends on used algos - // DHKEM X25519: Encapsuation 32 bytes, Poly1305 tag 16 bytes - const paddingLength = message_size - 4 - req.talerUri.length - 16 - 32; - const v = new DataView(headerBuf); - v.setUint32(0, 0); // FIXME message type, derive number from URI type! - const header = new Uint8Array(headerBuf); - const padding = new Uint8Array(paddingLength).fill(0); - const msg = new Uint8Array([...stringToBytes(req.talerUri), ...padding]); - const encryptedMessage = hpkeSealOneshot(decodeCrock(keys.encryptionKey), - stringToBytes("mailbox-message"), - header, - msg); + const encryptedMessage = encryptTalerUriMessage(decodeCrock(keys.encryptionKey), + req.talerUri, + paddedMessageSize); const resSend = await mailboxClient.sendMessage({ h_address: req.contact.mailboxAddress, - body: new Uint8Array([...header, ...encryptedMessage]), + body: encryptedMessage, }); switch (resSend.case) { case "ok":