aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrien Hopkins <[email protected]>2025-11-13 11:16:25 -0500
committerAdrien Hopkins <[email protected]>2025-11-13 11:16:25 -0500
commit3e4900606624220e6c112a5438698b03ee3c3943 (patch)
treea6ab495c0fac21f5db68409387c32fcdc24d4db0
parent05246ae8d0597ef86f912476ed0a369424d19a72 (diff)
downloadcoinos-ui-3e4900606624220e6c112a5438698b03ee3c3943.tar.gz
coinos-ui-3e4900606624220e6c112a5438698b03ee3c3943.zip
Add expiration timestamps to kind 13 seals
In case these leak, they will expire automatically. Currently, they use the same method as the gift wrap expirations: expiration + 2 days after the creation timestamp.
-rw-r--r--src/lib/nip17.ts36
1 files changed, 24 insertions, 12 deletions
diff --git a/src/lib/nip17.ts b/src/lib/nip17.ts
index 9dd59f6f..cb9a0573 100644
--- a/src/lib/nip17.ts
+++ b/src/lib/nip17.ts
@@ -10,9 +10,12 @@ const randomTimestamp = () => Math.floor(
// If wrapPK is specified and different than receiverPK,
// the message will be gift-wrapped to wrapPK
// but the rumour will be sent to receiverPK.
+// If expiryDays is specified, the message will expire in that many days,
+// plus a random amount from 0 to 2 for security.
+// (expiration time = random creation time + expiryDays + 2 days)
export const createNIP17MessageSK = (text: string, senderSK: Uint8Array, receiverPK: string, wrapPK: string = null, expiryDays: number = null) => {
const rumour = createRumour(text, getPublicKey(senderSK), receiverPK);
- const sealed = sealRumourSK(rumour, senderSK, wrapPK || receiverPK);
+ const sealed = sealRumourSK(rumour, senderSK, wrapPK || receiverPK, expiryDays);
return giftWrap(sealed, wrapPK || receiverPK, expiryDays);
}
@@ -25,7 +28,7 @@ export const createNIP17MessageSK = (text: string, senderSK: Uint8Array, receive
// (expiration time = random creation time + expiryDays + 2 days)
export const createNIP17MessageNIP07 = async (text: string, senderPK: string, receiverPK: string, wrapPK: string = null, expiryDays: number = null) => {
const rumour = createRumour(text, senderPK, receiverPK);
- const sealed = await sealRumourNip07(rumour, wrapPK || receiverPK);
+ const sealed = await sealRumourNip07(rumour, wrapPK || receiverPK, expiryDays);
return giftWrap(sealed, wrapPK || receiverPK, expiryDays);
}
@@ -41,32 +44,42 @@ const createRumour = (text: string, senderPK: string, receiverPK: string) => {
return rumour;
}
-const sealRumourSK = (rumour: object, senderSK: Uint8Array, receiverPK: string) => {
+const sealRumourSK = (rumour: object, senderSK: Uint8Array, receiverPK: string, expiryDays: number = null) => {
const senderSKString = bytesToHex(senderSK);
const conversationKey = u.getConversationKey(senderSKString, receiverPK);
const encryptedRumour = encrypt(JSON.stringify(rumour), conversationKey);
+ const created = randomTimestamp();
const sealEvent = {
kind: 13, // seal
- created_at: randomTimestamp(),
+ created_at: created,
tags: [],
pubkey: getPublicKey(senderSK),
content: encryptedRumour
}
+ if (expiryDays != null) {
+ const expiration = created + (expiryDays + 2) * 86400;
+ sealEvent.tags.push(["expiration", expiration.toString()]);
+ }
return finalizeEvent(sealEvent, senderSK);
}
-const sealRumourNip07 = async (rumour: object, receiverPK: string) => {
+const sealRumourNip07 = async (rumour: object, receiverPK: string, expiryDays: number = null) => {
const encryptedRumour = await window.nostr.nip44.encrypt(
receiverPK, JSON.stringify(rumour));
+ const created = randomTimestamp();
const sealEvent = {
kind: 13, // seal
- created_at: randomTimestamp(),
+ created_at: created,
tags: [],
content: encryptedRumour
}
+ if (expiryDays != null) {
+ const expiration = created + (expiryDays + 2) * 86400;
+ sealEvent.tags.push(["expiration", expiration.toString()]);
+ }
return window.nostr.signEvent(sealEvent);
}
@@ -77,19 +90,18 @@ const giftWrap = (event: object, receiverPK: string, expiryDays: number = null)
const conversationKey = u.getConversationKey(secretKey, receiverPK);
const encryptedEvent = encrypt(JSON.stringify(event), conversationKey);
const created = randomTimestamp();
- const tags = [["p", receiverPK]];
- if (expiryDays != null) {
- const expiration = created + (expiryDays + 2) * 86400;
- tags.push(["expiration", expiration.toString()]);
- }
const giftWrapEvent = {
kind: 1059, // gift wrap
created_at: created,
- tags: tags,
+ tags: [["p", receiverPK]],
pubkey: getPublicKey(secretKey),
content: encryptedEvent
}
+ if (expiryDays != null) {
+ const expiration = created + (expiryDays + 2) * 86400;
+ giftWrapEvent.tags.push(["expiration", expiration.toString()]);
+ }
return finalizeEvent(giftWrapEvent, secretKey);
}