@morseai/sdk 0.1.0-beta.5 → 0.1.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +5 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +86 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(crypto_x25519_exports, {
|
|
|
26
26
|
deriveKeyPairFromWalletSignature: () => deriveKeyPairFromWalletSignature,
|
|
27
27
|
generateSignalId: () => generateSignalId,
|
|
28
28
|
openSharedSignal: () => openSharedSignal,
|
|
29
|
+
sealDataKey: () => sealDataKey,
|
|
29
30
|
verifyKeyCertificate: () => verifyKeyCertificate
|
|
30
31
|
});
|
|
31
32
|
async function getSodium() {
|
|
@@ -285,6 +286,54 @@ async function openSharedSignal(encryptedPayloadBase64, payloadNonceBase64, seal
|
|
|
285
286
|
);
|
|
286
287
|
return payload;
|
|
287
288
|
}
|
|
289
|
+
async function sealDataKey(dataKeyBytes, walletTarget, walletCreator, expiresAt, signalId, domain, chainId, signMessage) {
|
|
290
|
+
await getSodium();
|
|
291
|
+
const senderKeypair = sodium.crypto_box_keypair();
|
|
292
|
+
const recipientKeypair = await deriveKeyPairFromWalletSignature(
|
|
293
|
+
walletTarget,
|
|
294
|
+
domain,
|
|
295
|
+
chainId,
|
|
296
|
+
signMessage
|
|
297
|
+
);
|
|
298
|
+
const recipientPubKey = recipientKeypair.publicKey;
|
|
299
|
+
const sharedSecret = sodium.crypto_scalarmult(
|
|
300
|
+
senderKeypair.privateKey,
|
|
301
|
+
recipientPubKey
|
|
302
|
+
);
|
|
303
|
+
const salt = `MORSE_SEAL_${signalId}_v1`;
|
|
304
|
+
const info = "wrap_datakey";
|
|
305
|
+
const wrappingKey = await hkdfSha256(sharedSecret, salt, info, 32);
|
|
306
|
+
const sealedNonce = sodium.randombytes_buf(sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
|
307
|
+
const expiresAtInt = Math.floor(Number(expiresAt));
|
|
308
|
+
const abiCoder = ethers.AbiCoder.defaultAbiCoder();
|
|
309
|
+
const senderEphemeralPubKeyHex = ethers.zeroPadValue(ethers.hexlify(senderKeypair.publicKey), 32);
|
|
310
|
+
const aad = abiCoder.encode(
|
|
311
|
+
["string", "address", "address", "uint64", "string", "bytes32"],
|
|
312
|
+
[
|
|
313
|
+
signalId,
|
|
314
|
+
walletTarget.toLowerCase(),
|
|
315
|
+
walletCreator.toLowerCase(),
|
|
316
|
+
expiresAtInt,
|
|
317
|
+
X25519_CIPHER_VERSION,
|
|
318
|
+
senderEphemeralPubKeyHex
|
|
319
|
+
]
|
|
320
|
+
);
|
|
321
|
+
const aadBytes = ethers.getBytes(aad);
|
|
322
|
+
const aadHash = ethers.keccak256(aad).slice(2);
|
|
323
|
+
const sealedDataKey = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(
|
|
324
|
+
dataKeyBytes,
|
|
325
|
+
aadBytes,
|
|
326
|
+
null,
|
|
327
|
+
sealedNonce,
|
|
328
|
+
wrappingKey
|
|
329
|
+
);
|
|
330
|
+
return {
|
|
331
|
+
sealedDataKey: Buffer.from(sealedDataKey).toString("base64"),
|
|
332
|
+
sealedNonce: Buffer.from(sealedNonce).toString("base64"),
|
|
333
|
+
senderEphemeralPublicKey: Buffer.from(senderKeypair.publicKey).toString("base64"),
|
|
334
|
+
aadHash
|
|
335
|
+
};
|
|
336
|
+
}
|
|
288
337
|
function generateSignalId() {
|
|
289
338
|
const bytes = new Uint8Array(16);
|
|
290
339
|
globalThis.crypto.getRandomValues(bytes);
|
|
@@ -622,7 +671,7 @@ async function decryptFile(encryptedData, ivBase64, key) {
|
|
|
622
671
|
return decrypted;
|
|
623
672
|
}
|
|
624
673
|
function generateShareableLink(baseUrl, signalId, keyBase64) {
|
|
625
|
-
return `${baseUrl}/view/${signalId}
|
|
674
|
+
return `${baseUrl}/view/${signalId}`;
|
|
626
675
|
}
|
|
627
676
|
|
|
628
677
|
// src/implementations/v1/MorseSDKV1.ts
|
|
@@ -1244,6 +1293,35 @@ var MorseSDKV1 = class {
|
|
|
1244
1293
|
async createPrivateSignalEncrypted(wallet, options) {
|
|
1245
1294
|
const key = await generateKey();
|
|
1246
1295
|
const keyBase64 = await exportKey(key);
|
|
1296
|
+
const signalId = options.signalId || generateSignalId();
|
|
1297
|
+
let expiresAtMs;
|
|
1298
|
+
if (options.expiresAt) {
|
|
1299
|
+
expiresAtMs = new Date(options.expiresAt).getTime();
|
|
1300
|
+
} else if (options.expiresIn) {
|
|
1301
|
+
const match = options.expiresIn.match(/^(\d+)([smhd])$/);
|
|
1302
|
+
if (!match) throw new Error("Invalid expiresIn format");
|
|
1303
|
+
const value = parseInt(match[1], 10);
|
|
1304
|
+
const unit = match[2];
|
|
1305
|
+
const multipliers = { s: 1e3, m: 6e4, h: 36e5, d: 864e5 };
|
|
1306
|
+
expiresAtMs = Date.now() + value * multipliers[unit];
|
|
1307
|
+
} else {
|
|
1308
|
+
expiresAtMs = Date.now() + 24 * 60 * 60 * 1e3;
|
|
1309
|
+
}
|
|
1310
|
+
const walletTarget = wallet.address;
|
|
1311
|
+
const walletCreator = wallet.address;
|
|
1312
|
+
const domain = "morse.app";
|
|
1313
|
+
const chainId = 8453;
|
|
1314
|
+
const keyBytes = this.base64ToUint8Array(keyBase64);
|
|
1315
|
+
const sealedBox = await sealDataKey(
|
|
1316
|
+
keyBytes,
|
|
1317
|
+
walletTarget.toLowerCase(),
|
|
1318
|
+
walletCreator.toLowerCase(),
|
|
1319
|
+
expiresAtMs,
|
|
1320
|
+
signalId,
|
|
1321
|
+
domain,
|
|
1322
|
+
chainId,
|
|
1323
|
+
wallet.signMessage
|
|
1324
|
+
);
|
|
1247
1325
|
let encryptedText;
|
|
1248
1326
|
let payloadNonce;
|
|
1249
1327
|
let fileOptions;
|
|
@@ -1270,6 +1348,7 @@ var MorseSDKV1 = class {
|
|
|
1270
1348
|
};
|
|
1271
1349
|
}
|
|
1272
1350
|
const signalOptions = {
|
|
1351
|
+
signalId,
|
|
1273
1352
|
walletTarget: options.walletTarget,
|
|
1274
1353
|
shareWithRecipient: options.shareWithRecipient,
|
|
1275
1354
|
mode: options.mode,
|
|
@@ -1278,16 +1357,18 @@ var MorseSDKV1 = class {
|
|
|
1278
1357
|
cipherVersion: getCipherVersion(),
|
|
1279
1358
|
encryptedText,
|
|
1280
1359
|
payloadNonce,
|
|
1360
|
+
sealedDataKey: sealedBox.sealedDataKey,
|
|
1361
|
+
sealedNonce: sealedBox.sealedNonce,
|
|
1362
|
+
senderEphemeralPublicKey: sealedBox.senderEphemeralPublicKey,
|
|
1363
|
+
aadHash: sealedBox.aadHash,
|
|
1281
1364
|
file: fileOptions,
|
|
1282
1365
|
onChainNotification: options.onChainNotification,
|
|
1283
|
-
expiresAt:
|
|
1284
|
-
expiresIn: options.expiresIn
|
|
1366
|
+
expiresAt: new Date(expiresAtMs).toISOString()
|
|
1285
1367
|
};
|
|
1286
1368
|
const result = await this.createSignal(wallet, signalOptions);
|
|
1287
|
-
const shareableLink = generateShareableLink(FRONTEND_BASE_URL, result.signalId
|
|
1369
|
+
const shareableLink = generateShareableLink(FRONTEND_BASE_URL, result.signalId);
|
|
1288
1370
|
return {
|
|
1289
1371
|
...result,
|
|
1290
|
-
keyBase64,
|
|
1291
1372
|
shareableLink
|
|
1292
1373
|
};
|
|
1293
1374
|
}
|
|
@@ -1385,8 +1466,6 @@ var MorseSDKV1 = class {
|
|
|
1385
1466
|
const shareableLink = `${FRONTEND_BASE_URL}/view/${result.signalId}`;
|
|
1386
1467
|
return {
|
|
1387
1468
|
...result,
|
|
1388
|
-
keyBase64: "",
|
|
1389
|
-
// No key needed for X25519 signals
|
|
1390
1469
|
shareableLink
|
|
1391
1470
|
};
|
|
1392
1471
|
}
|