@secrecy/lib 1.42.2 → 1.43.0-feat-unencrypted-data.1
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/dist/lib/client/SecrecyCloudClient.js +76 -35
- package/dist/lib/client/SecrecyMailClient.js +4 -2
- package/dist/lib/client/convert/data.js +5 -3
- package/dist/lib/client/convert/node.js +1 -1
- package/dist/lib/client.js +2 -1
- package/dist/types/client/SecrecyCloudClient.d.ts +4 -2
- package/dist/types/client/types/data.d.ts +2 -2
- package/dist/types/client/types/mail.d.ts +2 -2
- package/dist/types/client/types/node.d.ts +1 -1
- package/dist/types/client.d.ts +793 -6499
- package/package.json +5 -4
|
@@ -40,35 +40,52 @@ export class SecrecyCloudClient {
|
|
|
40
40
|
const userPubKey = await this.#client.app.userPublicKey(u.id);
|
|
41
41
|
return {
|
|
42
42
|
id: u.id,
|
|
43
|
-
key:
|
|
43
|
+
key: data.key
|
|
44
|
+
? sodium.to_hex(encryptCryptoBox(sodium.from_hex(data.key), userPubKey, this.#keys.privateKey))
|
|
45
|
+
: null,
|
|
44
46
|
};
|
|
45
47
|
})),
|
|
46
48
|
});
|
|
47
49
|
}
|
|
48
50
|
return internalNodeFullToNodeFull(node);
|
|
49
51
|
}
|
|
50
|
-
async uploadLiteData({ data, encryptProgress, uploadProgress, signal, }) {
|
|
52
|
+
async uploadLiteData({ data, encrypted = true, encryptProgress, uploadProgress, signal, }) {
|
|
51
53
|
const dataBuffer = data instanceof File ? new Uint8Array(await data.arrayBuffer()) : data;
|
|
52
54
|
if (dataBuffer.byteLength > kiloToBytes(4500)) {
|
|
53
55
|
throw new Error('The data is too big for lite upload!');
|
|
54
56
|
}
|
|
55
57
|
const compressed = compress(dataBuffer);
|
|
56
|
-
const dataKey = secretStreamKeygen();
|
|
57
|
-
const { data: encryptedData, md5: md5Data, md5Encrypted, } =
|
|
58
|
-
|
|
58
|
+
const dataKey = encrypted ? secretStreamKeygen() : null;
|
|
59
|
+
const { data: encryptedData, md5: md5Data, md5Encrypted, } = dataKey
|
|
60
|
+
? await encrypt(dataKey, compressed, encryptProgress, signal)
|
|
61
|
+
: {
|
|
62
|
+
data: compressed,
|
|
63
|
+
md5: await md5(compressed),
|
|
64
|
+
};
|
|
65
|
+
const encryptedDataKey = dataKey
|
|
66
|
+
? encryptCryptoBox(dataKey, this.#keys.publicKey, this.#keys.privateKey)
|
|
67
|
+
: null;
|
|
59
68
|
await uploadProgress?.({
|
|
60
69
|
total: encryptedData.byteLength,
|
|
61
70
|
current: 0,
|
|
62
71
|
percent: 0,
|
|
63
72
|
});
|
|
64
|
-
const uploadData = await this.#apiClient.cloud.uploadLiteData.mutate(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
const uploadData = await this.#apiClient.cloud.uploadLiteData.mutate(encryptedDataKey && md5Encrypted
|
|
74
|
+
? {
|
|
75
|
+
type: 'encrypted',
|
|
76
|
+
content: Buffer.from(encryptedData),
|
|
77
|
+
sizeEncrypted: BigInt(encryptedData.byteLength),
|
|
78
|
+
size: BigInt(dataBuffer.byteLength),
|
|
79
|
+
key: sodium.to_hex(encryptedDataKey),
|
|
80
|
+
md5Encrypted,
|
|
81
|
+
md5: md5Data,
|
|
82
|
+
}
|
|
83
|
+
: {
|
|
84
|
+
type: 'unencrypted',
|
|
85
|
+
content: Buffer.from(encryptedData),
|
|
86
|
+
md5: md5Data,
|
|
87
|
+
size: BigInt(dataBuffer.byteLength),
|
|
88
|
+
}, { signal });
|
|
72
89
|
await uploadProgress?.({
|
|
73
90
|
total: encryptedData.byteLength,
|
|
74
91
|
current: encryptedData.byteLength,
|
|
@@ -76,19 +93,33 @@ export class SecrecyCloudClient {
|
|
|
76
93
|
});
|
|
77
94
|
return uploadData.id;
|
|
78
95
|
}
|
|
79
|
-
async uploadData({ data, encryptProgress, uploadProgress, signal, }) {
|
|
80
|
-
const dataKey = secretStreamKeygen();
|
|
96
|
+
async uploadData({ data, encrypted = true, encryptProgress, uploadProgress, signal, }) {
|
|
97
|
+
const dataKey = encrypted ? secretStreamKeygen() : null;
|
|
81
98
|
const dataBuffer = data instanceof File ? new Uint8Array(await data.arrayBuffer()) : data;
|
|
82
99
|
const compressed = compress(dataBuffer);
|
|
83
|
-
const { data: encryptedData, md5: md5Data, md5Encrypted, } =
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
const { data: encryptedData, md5: md5Data, md5Encrypted, } = dataKey
|
|
101
|
+
? await encrypt(dataKey, compressed, encryptProgress, signal)
|
|
102
|
+
: {
|
|
103
|
+
data: compressed,
|
|
104
|
+
md5: await md5(compressed),
|
|
105
|
+
};
|
|
106
|
+
const encryptedDataKey = dataKey
|
|
107
|
+
? encryptCryptoBox(dataKey, this.#keys.publicKey, this.#keys.privateKey)
|
|
108
|
+
: null;
|
|
109
|
+
const uploadData = await this.#apiClient.cloud.uploadData.mutate(encryptedDataKey && md5Encrypted
|
|
110
|
+
? {
|
|
111
|
+
type: 'encrypted',
|
|
112
|
+
sizeEncrypted: BigInt(encryptedData.byteLength),
|
|
113
|
+
size: BigInt(dataBuffer.byteLength),
|
|
114
|
+
key: sodium.to_hex(encryptedDataKey),
|
|
115
|
+
md5Encrypted,
|
|
116
|
+
md5: md5Data,
|
|
117
|
+
}
|
|
118
|
+
: {
|
|
119
|
+
type: 'unencrypted',
|
|
120
|
+
md5: md5Data,
|
|
121
|
+
size: BigInt(dataBuffer.byteLength),
|
|
122
|
+
}, { signal });
|
|
92
123
|
await uploadProgress?.({
|
|
93
124
|
total: encryptedData.byteLength,
|
|
94
125
|
current: 0,
|
|
@@ -361,12 +392,16 @@ export class SecrecyCloudClient {
|
|
|
361
392
|
if (md5Encrypted !== dataContent.md5Encrypted) {
|
|
362
393
|
throw new Error(`Encrypted content does not match`);
|
|
363
394
|
}
|
|
364
|
-
const key =
|
|
365
|
-
? dataContent.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
395
|
+
const key = dataContent.key
|
|
396
|
+
? decryptCryptoBox(sodium.from_hex(dataContent.key), dataContent.type === 'received_mail'
|
|
397
|
+
? dataContent.senderPublicKey
|
|
398
|
+
: dataContent.type === 'cloud'
|
|
399
|
+
? dataContent.publicKey
|
|
400
|
+
: this.#keys.publicKey, this.#keys.privateKey)
|
|
401
|
+
: null;
|
|
402
|
+
const src = key
|
|
403
|
+
? await decrypt(key, encryptedContent, progressDecrypt, signal)
|
|
404
|
+
: encryptedContent;
|
|
370
405
|
// const md5Content = await firstValueFrom(md5(of(src)));
|
|
371
406
|
const md5Content = await md5(src);
|
|
372
407
|
if (md5Content !== dataContent.md5) {
|
|
@@ -433,7 +468,7 @@ export class SecrecyCloudClient {
|
|
|
433
468
|
throw err;
|
|
434
469
|
}
|
|
435
470
|
}
|
|
436
|
-
let key =
|
|
471
|
+
let key = null;
|
|
437
472
|
const data = dataCache.get(dataId);
|
|
438
473
|
if (data === undefined) {
|
|
439
474
|
await this.dataMetadata({ id: dataId });
|
|
@@ -459,8 +494,10 @@ export class SecrecyCloudClient {
|
|
|
459
494
|
throw err;
|
|
460
495
|
}
|
|
461
496
|
const senderPubKey = await this.#client.app.userPublicKey(mail.sender.id);
|
|
462
|
-
const dataKey =
|
|
463
|
-
|
|
497
|
+
const dataKey = attachment.key
|
|
498
|
+
? decryptCryptoBox(sodium.from_hex(attachment.key), senderPubKey, this.#keys.privateKey)
|
|
499
|
+
: null;
|
|
500
|
+
key = dataKey !== null ? sodium.to_hex(dataKey) : null;
|
|
464
501
|
}
|
|
465
502
|
else {
|
|
466
503
|
key = data.key;
|
|
@@ -469,7 +506,9 @@ export class SecrecyCloudClient {
|
|
|
469
506
|
else {
|
|
470
507
|
key = data.key;
|
|
471
508
|
}
|
|
472
|
-
key =
|
|
509
|
+
key = key
|
|
510
|
+
? sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), this.#keys.publicKey, this.#keys.privateKey))
|
|
511
|
+
: null;
|
|
473
512
|
const nameKey = secretStreamKeygen();
|
|
474
513
|
const encryptedName = await encryptName(name, sodium.to_hex(nameKey));
|
|
475
514
|
const encryptedNameKey = sodium.to_hex(encryptCryptoBox(nameKey, this.#keys.publicKey, this.#keys.privateKey));
|
|
@@ -511,7 +550,9 @@ export class SecrecyCloudClient {
|
|
|
511
550
|
data: 'history' in node
|
|
512
551
|
? node.history.map((f) => ({
|
|
513
552
|
id: f.id,
|
|
514
|
-
key:
|
|
553
|
+
key: f.key
|
|
554
|
+
? sodium.to_hex(encryptCryptoBox(sodium.from_hex(f.key), publicKey, this.#keys.privateKey))
|
|
555
|
+
: null,
|
|
515
556
|
}))
|
|
516
557
|
: [],
|
|
517
558
|
};
|
|
@@ -277,9 +277,11 @@ export class SecrecyMailClient {
|
|
|
277
277
|
}
|
|
278
278
|
const key = dataInHistory.key;
|
|
279
279
|
attachments.push({
|
|
280
|
-
|
|
280
|
+
dataId: f.id,
|
|
281
281
|
name: sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), pubKey, this.#keys.privateKey)),
|
|
282
|
-
key:
|
|
282
|
+
key: key
|
|
283
|
+
? sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), pubKey, this.#keys.privateKey))
|
|
284
|
+
: null,
|
|
283
285
|
});
|
|
284
286
|
}
|
|
285
287
|
return {
|
|
@@ -8,8 +8,10 @@ export function apiDataToInternal(apiData, keyPair) {
|
|
|
8
8
|
md5Encrypted: apiData.md5Encrypted,
|
|
9
9
|
createdAt: apiData.createdAt,
|
|
10
10
|
size: apiData.size,
|
|
11
|
-
|
|
12
|
-
key:
|
|
11
|
+
sizeEncrypted: apiData.sizeEncrypted,
|
|
12
|
+
key: apiData.access.key
|
|
13
|
+
? sodium.to_hex(decryptCryptoBox(sodium.from_hex(apiData.access.key), apiData.access.sharedByPubKey, keyPair.privateKey))
|
|
14
|
+
: null,
|
|
13
15
|
};
|
|
14
16
|
dataCache.set(data.id, data);
|
|
15
17
|
return data;
|
|
@@ -21,7 +23,7 @@ export function internalDataToExternalData(internal) {
|
|
|
21
23
|
md5Encrypted: internal.md5Encrypted,
|
|
22
24
|
createdAt: internal.createdAt,
|
|
23
25
|
size: internal.size,
|
|
24
|
-
|
|
26
|
+
sizeEncrypted: internal.sizeEncrypted,
|
|
25
27
|
};
|
|
26
28
|
}
|
|
27
29
|
export function apiDataToExternal(apiData, keyPair) {
|
package/dist/lib/client.js
CHANGED
|
@@ -11,7 +11,8 @@ superjson.registerCustom({
|
|
|
11
11
|
}, 'buffer');
|
|
12
12
|
export const getUrl = () => {
|
|
13
13
|
const protocol = process.env.NEXT_PUBLIC_VERCEL_ENV !== 'development' ? 'https' : 'http';
|
|
14
|
-
const url = process.env.NEXT_PUBLIC_VERCEL_ENV
|
|
14
|
+
const url = process.env.NEXT_PUBLIC_VERCEL_ENV &&
|
|
15
|
+
process.env.NEXT_PUBLIC_VERCEL_ENV !== 'production'
|
|
15
16
|
? `${process.env.NEXT_PUBLIC_VERCEL_URL}/api/trpc`
|
|
16
17
|
: `api.secrecy.tech/trpc`;
|
|
17
18
|
return `${protocol}://${url}`;
|
|
@@ -9,14 +9,16 @@ export declare class SecrecyCloudClient {
|
|
|
9
9
|
dataId: string;
|
|
10
10
|
nodeId: string;
|
|
11
11
|
}): Promise<NodeFull>;
|
|
12
|
-
uploadLiteData({ data, encryptProgress, uploadProgress, signal, }: {
|
|
12
|
+
uploadLiteData({ data, encrypted, encryptProgress, uploadProgress, signal, }: {
|
|
13
13
|
data: globalThis.File | Uint8Array;
|
|
14
|
+
encrypted?: boolean;
|
|
14
15
|
encryptProgress?: ProgressCallback;
|
|
15
16
|
uploadProgress?: ProgressCallback;
|
|
16
17
|
signal?: AbortSignal;
|
|
17
18
|
}): Promise<string>;
|
|
18
|
-
uploadData({ data, encryptProgress, uploadProgress, signal, }: {
|
|
19
|
+
uploadData({ data, encrypted, encryptProgress, uploadProgress, signal, }: {
|
|
19
20
|
data: globalThis.File | Uint8Array;
|
|
21
|
+
encrypted?: boolean;
|
|
20
22
|
encryptProgress?: ProgressCallback;
|
|
21
23
|
uploadProgress?: ProgressCallback;
|
|
22
24
|
signal?: AbortSignal;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type RouterOutputs } from '../../client.js';
|
|
2
|
-
export type DataMetadata = Pick<ApiData, 'id' | 'size' | '
|
|
2
|
+
export type DataMetadata = Pick<ApiData, 'id' | 'size' | 'sizeEncrypted' | 'md5' | 'md5Encrypted' | 'createdAt'>;
|
|
3
3
|
export type InternalData = DataMetadata & {
|
|
4
|
-
key: string;
|
|
4
|
+
key: string | null;
|
|
5
5
|
};
|
|
6
6
|
export type ApiData = NonNullable<RouterOutputs['cloud']['dataById']>;
|
|
@@ -18,7 +18,7 @@ export interface BaseMail {
|
|
|
18
18
|
attachments: Array<{
|
|
19
19
|
id: string;
|
|
20
20
|
name: string;
|
|
21
|
-
key: string;
|
|
21
|
+
key: string | null;
|
|
22
22
|
}>;
|
|
23
23
|
}
|
|
24
24
|
export interface ReceivedMail extends BaseMail {
|
|
@@ -75,7 +75,7 @@ export interface WaitingReceivedMail {
|
|
|
75
75
|
temporaryRecipients: TemporaryMailUser[];
|
|
76
76
|
}
|
|
77
77
|
export interface MailData {
|
|
78
|
-
dataKey: string;
|
|
78
|
+
dataKey: string | null;
|
|
79
79
|
dataName: string;
|
|
80
80
|
data: {
|
|
81
81
|
id: string;
|