wolfronix-sdk 1.2.0 → 1.3.0
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 +28 -35
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +37 -15
- package/dist/index.mjs +37 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# wolfronix-sdk
|
|
2
2
|
|
|
3
3
|
Official JavaScript/TypeScript SDK for Wolfronix - Zero-knowledge encryption made simple.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/wolfronix-sdk)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
10
|
- 🔐 **Zero-Knowledge Encryption** - Keys generated client-side, never leave your device
|
|
11
11
|
- 🏢 **Enterprise Ready** - Seamless integration with your existing storage
|
|
12
|
-
|
|
13
12
|
- 🚀 **Simple API** - Encrypt files in 2 lines of code
|
|
14
13
|
- 📦 **TypeScript Native** - Full type definitions included
|
|
15
|
-
- 🌐 **Universal** - Works in Node.js and browsers
|
|
16
|
-
- ⚡ **Streaming** - Handle large files with progress tracking
|
|
14
|
+
- 🌐 **Universal** - Works in Node.js 16+ and modern browsers
|
|
17
15
|
- 🔄 **Auto Retry** - Built-in retry logic with exponential backoff
|
|
18
16
|
|
|
19
17
|
## Backend Integration (Enterprise Mode)
|
|
@@ -30,17 +28,17 @@ Wolfronix handles all encryption/decryption keys and logic; you only handle the
|
|
|
30
28
|
## Installation
|
|
31
29
|
|
|
32
30
|
```bash
|
|
33
|
-
npm install
|
|
31
|
+
npm install wolfronix-sdk
|
|
34
32
|
# or
|
|
35
|
-
yarn add
|
|
33
|
+
yarn add wolfronix-sdk
|
|
36
34
|
# or
|
|
37
|
-
pnpm add
|
|
35
|
+
pnpm add wolfronix-sdk
|
|
38
36
|
```
|
|
39
37
|
|
|
40
38
|
## Quick Start
|
|
41
39
|
|
|
42
40
|
```typescript
|
|
43
|
-
import Wolfronix from '
|
|
41
|
+
import Wolfronix from 'wolfronix-sdk';
|
|
44
42
|
|
|
45
43
|
// Initialize client
|
|
46
44
|
const wfx = new Wolfronix({
|
|
@@ -67,7 +65,7 @@ const decrypted = await wfx.decrypt(result.file_id);
|
|
|
67
65
|
### Browser (React, Vue, Angular, etc.)
|
|
68
66
|
|
|
69
67
|
```typescript
|
|
70
|
-
import Wolfronix from '
|
|
68
|
+
import Wolfronix from 'wolfronix-sdk';
|
|
71
69
|
|
|
72
70
|
const wfx = new Wolfronix('https://wolfronix-server:5002');
|
|
73
71
|
|
|
@@ -77,7 +75,6 @@ const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
|
77
75
|
if (!file) return;
|
|
78
76
|
|
|
79
77
|
try {
|
|
80
|
-
// Keys are automatically handled by the SDK
|
|
81
78
|
const { file_id } = await wfx.encrypt(file);
|
|
82
79
|
console.log('File encrypted with your private key:', file_id);
|
|
83
80
|
} catch (error) {
|
|
@@ -102,7 +99,7 @@ const handleDownload = async (fileId: string, filename: string) => {
|
|
|
102
99
|
### Node.js
|
|
103
100
|
|
|
104
101
|
```typescript
|
|
105
|
-
import Wolfronix from '
|
|
102
|
+
import Wolfronix from 'wolfronix-sdk';
|
|
106
103
|
import * as fs from 'fs';
|
|
107
104
|
|
|
108
105
|
const wfx = new Wolfronix({
|
|
@@ -132,23 +129,6 @@ async function main() {
|
|
|
132
129
|
main();
|
|
133
130
|
```
|
|
134
131
|
|
|
135
|
-
### Large File Streaming with Progress
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
const wfx = new Wolfronix('https://wolfronix-server:5002');
|
|
139
|
-
|
|
140
|
-
// Encrypt with progress
|
|
141
|
-
const result = await wfx.encryptStream(largeFile, (percent) => {
|
|
142
|
-
console.log(`Uploading: ${percent}%`);
|
|
143
|
-
progressBar.value = percent;
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// Decrypt with progress
|
|
147
|
-
const blob = await wfx.decryptStream(fileId, (percent) => {
|
|
148
|
-
console.log(`Downloading: ${percent}%`);
|
|
149
|
-
});
|
|
150
|
-
```
|
|
151
|
-
|
|
152
132
|
## API Reference
|
|
153
133
|
|
|
154
134
|
### Constructor
|
|
@@ -181,10 +161,8 @@ new Wolfronix(config: WolfronixConfig | string)
|
|
|
181
161
|
| Method | Description |
|
|
182
162
|
|--------|-------------|
|
|
183
163
|
| `encrypt(file, filename?)` | Encrypt and store file |
|
|
184
|
-
| `encryptStream(file, onProgress?)` | Encrypt large file with progress |
|
|
185
164
|
| `decrypt(fileId)` | Decrypt file (returns Blob) |
|
|
186
165
|
| `decryptToBuffer(fileId)` | Decrypt file (returns ArrayBuffer) |
|
|
187
|
-
| `decryptStream(fileId, onProgress?)` | Decrypt large file with progress |
|
|
188
166
|
| `listFiles()` | List user's encrypted files |
|
|
189
167
|
| `deleteFile(fileId)` | Delete encrypted file |
|
|
190
168
|
|
|
@@ -207,7 +185,7 @@ import Wolfronix, {
|
|
|
207
185
|
PermissionDeniedError,
|
|
208
186
|
NetworkError,
|
|
209
187
|
ValidationError
|
|
210
|
-
} from '
|
|
188
|
+
} from 'wolfronix-sdk';
|
|
211
189
|
|
|
212
190
|
try {
|
|
213
191
|
await wfx.encrypt(file);
|
|
@@ -246,7 +224,7 @@ import Wolfronix, {
|
|
|
246
224
|
FileInfo,
|
|
247
225
|
ListFilesResponse,
|
|
248
226
|
MetricsResponse
|
|
249
|
-
} from '
|
|
227
|
+
} from 'wolfronix-sdk';
|
|
250
228
|
|
|
251
229
|
// All methods are fully typed
|
|
252
230
|
const config: WolfronixConfig = {
|
|
@@ -263,7 +241,7 @@ const response: EncryptResponse = await wfx.encrypt(file);
|
|
|
263
241
|
```typescript
|
|
264
242
|
// useWolfronix.ts
|
|
265
243
|
import { useState, useCallback, useMemo } from 'react';
|
|
266
|
-
import Wolfronix, { FileInfo as WolfronixFile } from '
|
|
244
|
+
import Wolfronix, { FileInfo as WolfronixFile } from 'wolfronix-sdk';
|
|
267
245
|
|
|
268
246
|
export function useWolfronix(baseUrl: string, clientId?: string) {
|
|
269
247
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -351,10 +329,25 @@ function FileManager() {
|
|
|
351
329
|
}
|
|
352
330
|
```
|
|
353
331
|
|
|
332
|
+
## Real-World Use Cases
|
|
333
|
+
|
|
334
|
+
Wolfronix can be integrated into **any application** that handles sensitive data:
|
|
335
|
+
|
|
336
|
+
| Industry | Application | How Wolfronix Helps |
|
|
337
|
+
|----------|------------|---------------------|
|
|
338
|
+
| 🏥 **Healthcare** | Patient records, lab reports | HIPAA-compliant encryption at rest |
|
|
339
|
+
| 🏦 **Finance** | Invoices, tax docs, receipts | End-to-end encrypted banking documents |
|
|
340
|
+
| ⚖️ **Legal** | Contracts, case files | Zero-knowledge confidential storage |
|
|
341
|
+
| ☁️ **Cloud Storage** | Drive/Dropbox alternatives | Encrypted file vault with user-owned keys |
|
|
342
|
+
| 🏢 **Enterprise** | HR records, internal docs | Per-employee encryption isolation |
|
|
343
|
+
| 🎓 **Education** | Exam papers, student data | Tamper-proof academic records |
|
|
344
|
+
| 💬 **Messaging** | File attachments | Encrypted file sharing in chat apps |
|
|
345
|
+
| 🛒 **E-commerce** | Order docs, payment receipts | PCI-compliant document storage |
|
|
346
|
+
|
|
354
347
|
## Requirements
|
|
355
348
|
|
|
356
349
|
- Node.js 16+ (for Node.js usage)
|
|
357
|
-
- Modern browser with
|
|
350
|
+
- Modern browser with Web Crypto API support
|
|
358
351
|
|
|
359
352
|
## License
|
|
360
353
|
|
package/dist/index.d.mts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Zero-knowledge encryption made simple
|
|
4
4
|
*
|
|
5
5
|
* @package @wolfronix/sdk
|
|
6
|
-
* @version 1.
|
|
6
|
+
* @version 1.3.0
|
|
7
7
|
*/
|
|
8
8
|
interface WolfronixConfig {
|
|
9
9
|
/** Wolfronix server base URL */
|
|
@@ -25,7 +25,7 @@ interface AuthResponse {
|
|
|
25
25
|
}
|
|
26
26
|
interface EncryptResponse {
|
|
27
27
|
status: string;
|
|
28
|
-
file_id:
|
|
28
|
+
file_id: string;
|
|
29
29
|
file_size: number;
|
|
30
30
|
enc_time_ms: number;
|
|
31
31
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Zero-knowledge encryption made simple
|
|
4
4
|
*
|
|
5
5
|
* @package @wolfronix/sdk
|
|
6
|
-
* @version 1.
|
|
6
|
+
* @version 1.3.0
|
|
7
7
|
*/
|
|
8
8
|
interface WolfronixConfig {
|
|
9
9
|
/** Wolfronix server base URL */
|
|
@@ -25,7 +25,7 @@ interface AuthResponse {
|
|
|
25
25
|
}
|
|
26
26
|
interface EncryptResponse {
|
|
27
27
|
status: string;
|
|
28
|
-
file_id:
|
|
28
|
+
file_id: string;
|
|
29
29
|
file_size: number;
|
|
30
30
|
enc_time_ms: number;
|
|
31
31
|
}
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,14 @@ __export(index_exports, {
|
|
|
33
33
|
module.exports = __toCommonJS(index_exports);
|
|
34
34
|
|
|
35
35
|
// src/crypto.ts
|
|
36
|
+
var getCrypto = () => {
|
|
37
|
+
if (typeof globalThis.crypto !== "undefined") {
|
|
38
|
+
return globalThis.crypto;
|
|
39
|
+
}
|
|
40
|
+
throw new Error(
|
|
41
|
+
"Web Crypto API not available. Requires a modern browser or Node.js 16+."
|
|
42
|
+
);
|
|
43
|
+
};
|
|
36
44
|
var RSA_ALG = {
|
|
37
45
|
name: "RSA-OAEP",
|
|
38
46
|
modulusLength: 2048,
|
|
@@ -42,7 +50,7 @@ var RSA_ALG = {
|
|
|
42
50
|
var WRAP_ALG = "AES-GCM";
|
|
43
51
|
var PBKDF2_ITERATIONS = 1e5;
|
|
44
52
|
async function generateKeyPair() {
|
|
45
|
-
return await
|
|
53
|
+
return await getCrypto().subtle.generateKey(
|
|
46
54
|
RSA_ALG,
|
|
47
55
|
true,
|
|
48
56
|
// extractable
|
|
@@ -51,7 +59,7 @@ async function generateKeyPair() {
|
|
|
51
59
|
}
|
|
52
60
|
async function exportKeyToPEM(key, type) {
|
|
53
61
|
const format = type === "public" ? "spki" : "pkcs8";
|
|
54
|
-
const exported = await
|
|
62
|
+
const exported = await getCrypto().subtle.exportKey(format, key);
|
|
55
63
|
const exportedAsBase64 = arrayBufferToBase64(exported);
|
|
56
64
|
const pemHeader = type === "public" ? "-----BEGIN PUBLIC KEY-----" : "-----BEGIN PRIVATE KEY-----";
|
|
57
65
|
const pemFooter = type === "public" ? "-----END PUBLIC KEY-----" : "-----END PRIVATE KEY-----";
|
|
@@ -66,7 +74,7 @@ async function importKeyFromPEM(pem, type) {
|
|
|
66
74
|
const binaryDer = base64ToArrayBuffer(pemContents);
|
|
67
75
|
const format = type === "public" ? "spki" : "pkcs8";
|
|
68
76
|
const usage = type === "public" ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"];
|
|
69
|
-
return await
|
|
77
|
+
return await getCrypto().subtle.importKey(
|
|
70
78
|
format,
|
|
71
79
|
binaryDer,
|
|
72
80
|
RSA_ALG,
|
|
@@ -76,7 +84,7 @@ async function importKeyFromPEM(pem, type) {
|
|
|
76
84
|
}
|
|
77
85
|
async function deriveWrappingKey(password, saltHex) {
|
|
78
86
|
const enc = new TextEncoder();
|
|
79
|
-
const passwordKey = await
|
|
87
|
+
const passwordKey = await getCrypto().subtle.importKey(
|
|
80
88
|
"raw",
|
|
81
89
|
enc.encode(password),
|
|
82
90
|
"PBKDF2",
|
|
@@ -84,7 +92,7 @@ async function deriveWrappingKey(password, saltHex) {
|
|
|
84
92
|
["deriveKey"]
|
|
85
93
|
);
|
|
86
94
|
const salt = hexToArrayBuffer(saltHex);
|
|
87
|
-
return await
|
|
95
|
+
return await getCrypto().subtle.deriveKey(
|
|
88
96
|
{
|
|
89
97
|
name: "PBKDF2",
|
|
90
98
|
salt,
|
|
@@ -98,12 +106,13 @@ async function deriveWrappingKey(password, saltHex) {
|
|
|
98
106
|
);
|
|
99
107
|
}
|
|
100
108
|
async function wrapPrivateKey(privateKey, password) {
|
|
101
|
-
const
|
|
109
|
+
const crypto = getCrypto();
|
|
110
|
+
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
102
111
|
const saltHex = arrayBufferToHex(salt.buffer);
|
|
103
112
|
const wrappingKey = await deriveWrappingKey(password, saltHex);
|
|
104
|
-
const exportedKey = await
|
|
105
|
-
const iv =
|
|
106
|
-
const encryptedContent = await
|
|
113
|
+
const exportedKey = await crypto.subtle.exportKey("pkcs8", privateKey);
|
|
114
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
115
|
+
const encryptedContent = await crypto.subtle.encrypt(
|
|
107
116
|
{
|
|
108
117
|
name: WRAP_ALG,
|
|
109
118
|
iv
|
|
@@ -125,7 +134,7 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
|
|
|
125
134
|
const iv = combinedArray.slice(0, 12);
|
|
126
135
|
const data = combinedArray.slice(12);
|
|
127
136
|
const wrappingKey = await deriveWrappingKey(password, saltHex);
|
|
128
|
-
const decryptedKeyData = await
|
|
137
|
+
const decryptedKeyData = await getCrypto().subtle.decrypt(
|
|
129
138
|
{
|
|
130
139
|
name: WRAP_ALG,
|
|
131
140
|
iv
|
|
@@ -133,7 +142,7 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
|
|
|
133
142
|
wrappingKey,
|
|
134
143
|
data
|
|
135
144
|
);
|
|
136
|
-
return await
|
|
145
|
+
return await getCrypto().subtle.importKey(
|
|
137
146
|
"pkcs8",
|
|
138
147
|
decryptedKeyData,
|
|
139
148
|
RSA_ALG,
|
|
@@ -142,16 +151,23 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
|
|
|
142
151
|
);
|
|
143
152
|
}
|
|
144
153
|
function arrayBufferToBase64(buffer) {
|
|
145
|
-
let binary = "";
|
|
146
154
|
const bytes = new Uint8Array(buffer);
|
|
155
|
+
if (typeof Buffer !== "undefined") {
|
|
156
|
+
return Buffer.from(bytes).toString("base64");
|
|
157
|
+
}
|
|
158
|
+
let binary = "";
|
|
147
159
|
const len = bytes.byteLength;
|
|
148
160
|
for (let i = 0; i < len; i++) {
|
|
149
161
|
binary += String.fromCharCode(bytes[i]);
|
|
150
162
|
}
|
|
151
|
-
return
|
|
163
|
+
return btoa(binary);
|
|
152
164
|
}
|
|
153
165
|
function base64ToArrayBuffer(base64) {
|
|
154
|
-
|
|
166
|
+
if (typeof Buffer !== "undefined") {
|
|
167
|
+
const buf = Buffer.from(base64, "base64");
|
|
168
|
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
169
|
+
}
|
|
170
|
+
const binary_string = atob(base64);
|
|
155
171
|
const len = binary_string.length;
|
|
156
172
|
const bytes = new Uint8Array(len);
|
|
157
173
|
for (let i = 0; i < len; i++) {
|
|
@@ -492,9 +508,15 @@ var Wolfronix = class {
|
|
|
492
508
|
throw new Error("Public key not available. Is user logged in?");
|
|
493
509
|
}
|
|
494
510
|
formData.append("client_public_key", this.publicKeyPEM);
|
|
495
|
-
|
|
511
|
+
const response = await this.request("POST", "/api/v1/encrypt", {
|
|
496
512
|
formData
|
|
497
513
|
});
|
|
514
|
+
return {
|
|
515
|
+
status: response.status,
|
|
516
|
+
file_id: String(response.file_id),
|
|
517
|
+
file_size: response.file_size,
|
|
518
|
+
enc_time_ms: response.enc_time_ms
|
|
519
|
+
};
|
|
498
520
|
}
|
|
499
521
|
/**
|
|
500
522
|
* Decrypt and retrieve a file
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
// src/crypto.ts
|
|
2
|
+
var getCrypto = () => {
|
|
3
|
+
if (typeof globalThis.crypto !== "undefined") {
|
|
4
|
+
return globalThis.crypto;
|
|
5
|
+
}
|
|
6
|
+
throw new Error(
|
|
7
|
+
"Web Crypto API not available. Requires a modern browser or Node.js 16+."
|
|
8
|
+
);
|
|
9
|
+
};
|
|
2
10
|
var RSA_ALG = {
|
|
3
11
|
name: "RSA-OAEP",
|
|
4
12
|
modulusLength: 2048,
|
|
@@ -8,7 +16,7 @@ var RSA_ALG = {
|
|
|
8
16
|
var WRAP_ALG = "AES-GCM";
|
|
9
17
|
var PBKDF2_ITERATIONS = 1e5;
|
|
10
18
|
async function generateKeyPair() {
|
|
11
|
-
return await
|
|
19
|
+
return await getCrypto().subtle.generateKey(
|
|
12
20
|
RSA_ALG,
|
|
13
21
|
true,
|
|
14
22
|
// extractable
|
|
@@ -17,7 +25,7 @@ async function generateKeyPair() {
|
|
|
17
25
|
}
|
|
18
26
|
async function exportKeyToPEM(key, type) {
|
|
19
27
|
const format = type === "public" ? "spki" : "pkcs8";
|
|
20
|
-
const exported = await
|
|
28
|
+
const exported = await getCrypto().subtle.exportKey(format, key);
|
|
21
29
|
const exportedAsBase64 = arrayBufferToBase64(exported);
|
|
22
30
|
const pemHeader = type === "public" ? "-----BEGIN PUBLIC KEY-----" : "-----BEGIN PRIVATE KEY-----";
|
|
23
31
|
const pemFooter = type === "public" ? "-----END PUBLIC KEY-----" : "-----END PRIVATE KEY-----";
|
|
@@ -32,7 +40,7 @@ async function importKeyFromPEM(pem, type) {
|
|
|
32
40
|
const binaryDer = base64ToArrayBuffer(pemContents);
|
|
33
41
|
const format = type === "public" ? "spki" : "pkcs8";
|
|
34
42
|
const usage = type === "public" ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"];
|
|
35
|
-
return await
|
|
43
|
+
return await getCrypto().subtle.importKey(
|
|
36
44
|
format,
|
|
37
45
|
binaryDer,
|
|
38
46
|
RSA_ALG,
|
|
@@ -42,7 +50,7 @@ async function importKeyFromPEM(pem, type) {
|
|
|
42
50
|
}
|
|
43
51
|
async function deriveWrappingKey(password, saltHex) {
|
|
44
52
|
const enc = new TextEncoder();
|
|
45
|
-
const passwordKey = await
|
|
53
|
+
const passwordKey = await getCrypto().subtle.importKey(
|
|
46
54
|
"raw",
|
|
47
55
|
enc.encode(password),
|
|
48
56
|
"PBKDF2",
|
|
@@ -50,7 +58,7 @@ async function deriveWrappingKey(password, saltHex) {
|
|
|
50
58
|
["deriveKey"]
|
|
51
59
|
);
|
|
52
60
|
const salt = hexToArrayBuffer(saltHex);
|
|
53
|
-
return await
|
|
61
|
+
return await getCrypto().subtle.deriveKey(
|
|
54
62
|
{
|
|
55
63
|
name: "PBKDF2",
|
|
56
64
|
salt,
|
|
@@ -64,12 +72,13 @@ async function deriveWrappingKey(password, saltHex) {
|
|
|
64
72
|
);
|
|
65
73
|
}
|
|
66
74
|
async function wrapPrivateKey(privateKey, password) {
|
|
67
|
-
const
|
|
75
|
+
const crypto = getCrypto();
|
|
76
|
+
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
68
77
|
const saltHex = arrayBufferToHex(salt.buffer);
|
|
69
78
|
const wrappingKey = await deriveWrappingKey(password, saltHex);
|
|
70
|
-
const exportedKey = await
|
|
71
|
-
const iv =
|
|
72
|
-
const encryptedContent = await
|
|
79
|
+
const exportedKey = await crypto.subtle.exportKey("pkcs8", privateKey);
|
|
80
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
81
|
+
const encryptedContent = await crypto.subtle.encrypt(
|
|
73
82
|
{
|
|
74
83
|
name: WRAP_ALG,
|
|
75
84
|
iv
|
|
@@ -91,7 +100,7 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
|
|
|
91
100
|
const iv = combinedArray.slice(0, 12);
|
|
92
101
|
const data = combinedArray.slice(12);
|
|
93
102
|
const wrappingKey = await deriveWrappingKey(password, saltHex);
|
|
94
|
-
const decryptedKeyData = await
|
|
103
|
+
const decryptedKeyData = await getCrypto().subtle.decrypt(
|
|
95
104
|
{
|
|
96
105
|
name: WRAP_ALG,
|
|
97
106
|
iv
|
|
@@ -99,7 +108,7 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
|
|
|
99
108
|
wrappingKey,
|
|
100
109
|
data
|
|
101
110
|
);
|
|
102
|
-
return await
|
|
111
|
+
return await getCrypto().subtle.importKey(
|
|
103
112
|
"pkcs8",
|
|
104
113
|
decryptedKeyData,
|
|
105
114
|
RSA_ALG,
|
|
@@ -108,16 +117,23 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
|
|
|
108
117
|
);
|
|
109
118
|
}
|
|
110
119
|
function arrayBufferToBase64(buffer) {
|
|
111
|
-
let binary = "";
|
|
112
120
|
const bytes = new Uint8Array(buffer);
|
|
121
|
+
if (typeof Buffer !== "undefined") {
|
|
122
|
+
return Buffer.from(bytes).toString("base64");
|
|
123
|
+
}
|
|
124
|
+
let binary = "";
|
|
113
125
|
const len = bytes.byteLength;
|
|
114
126
|
for (let i = 0; i < len; i++) {
|
|
115
127
|
binary += String.fromCharCode(bytes[i]);
|
|
116
128
|
}
|
|
117
|
-
return
|
|
129
|
+
return btoa(binary);
|
|
118
130
|
}
|
|
119
131
|
function base64ToArrayBuffer(base64) {
|
|
120
|
-
|
|
132
|
+
if (typeof Buffer !== "undefined") {
|
|
133
|
+
const buf = Buffer.from(base64, "base64");
|
|
134
|
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
135
|
+
}
|
|
136
|
+
const binary_string = atob(base64);
|
|
121
137
|
const len = binary_string.length;
|
|
122
138
|
const bytes = new Uint8Array(len);
|
|
123
139
|
for (let i = 0; i < len; i++) {
|
|
@@ -458,9 +474,15 @@ var Wolfronix = class {
|
|
|
458
474
|
throw new Error("Public key not available. Is user logged in?");
|
|
459
475
|
}
|
|
460
476
|
formData.append("client_public_key", this.publicKeyPEM);
|
|
461
|
-
|
|
477
|
+
const response = await this.request("POST", "/api/v1/encrypt", {
|
|
462
478
|
formData
|
|
463
479
|
});
|
|
480
|
+
return {
|
|
481
|
+
status: response.status,
|
|
482
|
+
file_id: String(response.file_id),
|
|
483
|
+
file_size: response.file_size,
|
|
484
|
+
enc_time_ms: response.enc_time_ms
|
|
485
|
+
};
|
|
464
486
|
}
|
|
465
487
|
/**
|
|
466
488
|
* Decrypt and retrieve a file
|