@morseai/sdk 0.1.0-beta.6 → 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/README.md +1 -1
- package/dist/index.js +85 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +85 -3
- 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);
|
|
@@ -1243,7 +1292,36 @@ var MorseSDKV1 = class {
|
|
|
1243
1292
|
}
|
|
1244
1293
|
async createPrivateSignalEncrypted(wallet, options) {
|
|
1245
1294
|
const key = await generateKey();
|
|
1246
|
-
await exportKey(key);
|
|
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,10 +1357,13 @@ 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
1369
|
const shareableLink = generateShareableLink(FRONTEND_BASE_URL, result.signalId);
|