commit 4002f124f2bfe26e5084012ed6d1cda56ddee37a
parent 9835654765454e1cdf3adb311d4c1ff878a8f21b
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Fri, 7 Nov 2025 21:23:39 +0100
minor refactoring
Diffstat:
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":