wolfronix-sdk 1.3.0 → 1.3.2
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 +49 -0
- package/dist/index.d.mts +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +137 -0
- package/dist/index.mjs +137 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -127,8 +127,49 @@ async function main() {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
main();
|
|
130
|
+
// Decrypt and save
|
|
131
|
+
const decrypted = await wfx.decryptToBuffer(file_id);
|
|
132
|
+
fs.writeFileSync('decrypted.pdf', Buffer.from(decrypted));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
main();
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 💬 E2E Encrypted Chat Integration
|
|
139
|
+
|
|
140
|
+
Turn any chat app into a secure, end-to-end encrypted messenger in minutes.
|
|
141
|
+
|
|
142
|
+
**Sender (Alice):**
|
|
143
|
+
```typescript
|
|
144
|
+
// 1. Get Bob's Public Key & Encrypt Message
|
|
145
|
+
const securePacket = await wfx.encryptMessage("Secret details at 5 PM", "bob_user_id");
|
|
146
|
+
|
|
147
|
+
// 2. Send 'securePacket' string via your normal chat API (Socket.io, Firebase, etc.)
|
|
148
|
+
chatSocket.emit('message', {
|
|
149
|
+
to: 'bob',
|
|
150
|
+
text: securePacket // Valid JSON string
|
|
151
|
+
});
|
|
130
152
|
```
|
|
131
153
|
|
|
154
|
+
**Recipient (Bob):**
|
|
155
|
+
```typescript
|
|
156
|
+
// 1. Receive message from chat server
|
|
157
|
+
chatSocket.on('message', async (msg) => {
|
|
158
|
+
try {
|
|
159
|
+
// 2. Decrypt locally with Bob's Private Key
|
|
160
|
+
const plainText = await wfx.decryptMessage(msg.text);
|
|
161
|
+
console.log("Decrypted:", plainText);
|
|
162
|
+
} catch (err) {
|
|
163
|
+
console.error("Could not decrypt message");
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Features:**
|
|
169
|
+
- **Hybrid Encryption:** Uses AES-256 for messages + RSA-2048 for key exchange (Fast & Secure).
|
|
170
|
+
- **Zero-Knowledge:** Your chat server only sees encrypted packets.
|
|
171
|
+
- **Universal:** Works with any backend (Socket.io, Firebase, PostgreSQL, etc).
|
|
172
|
+
|
|
132
173
|
## API Reference
|
|
133
174
|
|
|
134
175
|
### Constructor
|
|
@@ -166,6 +207,14 @@ new Wolfronix(config: WolfronixConfig | string)
|
|
|
166
207
|
| `listFiles()` | List user's encrypted files |
|
|
167
208
|
| `deleteFile(fileId)` | Delete encrypted file |
|
|
168
209
|
|
|
210
|
+
### E2E Chat Encryption
|
|
211
|
+
|
|
212
|
+
| Method | Description |
|
|
213
|
+
|--------|-------------|
|
|
214
|
+
| `getPublicKey(userId)` | Fetch a user's RSA public key |
|
|
215
|
+
| `encryptMessage(text, recipientId)` | Encrypt text for a recipient (returns packet string) |
|
|
216
|
+
| `decryptMessage(packetString)` | Decrypt a received message packet |
|
|
217
|
+
|
|
169
218
|
### Utility
|
|
170
219
|
|
|
171
220
|
| Method | Description |
|
package/dist/index.d.mts
CHANGED
|
@@ -51,6 +51,11 @@ interface MetricsResponse {
|
|
|
51
51
|
total_bytes_encrypted: number;
|
|
52
52
|
total_bytes_decrypted: number;
|
|
53
53
|
}
|
|
54
|
+
interface EncryptMessagePacket {
|
|
55
|
+
key: string;
|
|
56
|
+
iv: string;
|
|
57
|
+
msg: string;
|
|
58
|
+
}
|
|
54
59
|
declare class WolfronixError extends Error {
|
|
55
60
|
readonly code: string;
|
|
56
61
|
readonly statusCode?: number;
|
|
@@ -188,6 +193,25 @@ declare class Wolfronix {
|
|
|
188
193
|
* ```
|
|
189
194
|
*/
|
|
190
195
|
deleteFile(fileId: string): Promise<DeleteResponse>;
|
|
196
|
+
/**
|
|
197
|
+
* Get another user's public key (for E2E encryption)
|
|
198
|
+
* @param userId The ID of the recipient
|
|
199
|
+
*/
|
|
200
|
+
getPublicKey(userId: string): Promise<string>;
|
|
201
|
+
/**
|
|
202
|
+
* Encrypt a short text message for a recipient (Hybrid Encryption: RSA + AES)
|
|
203
|
+
* Returns a secure JSON string (packet) to send via chat
|
|
204
|
+
*
|
|
205
|
+
* @param text The plain text message
|
|
206
|
+
* @param recipientId The recipient's user ID
|
|
207
|
+
*/
|
|
208
|
+
encryptMessage(text: string, recipientId: string): Promise<string>;
|
|
209
|
+
/**
|
|
210
|
+
* Decrypt a message packet received from chat
|
|
211
|
+
*
|
|
212
|
+
* @param packetJson The secure JSON string packet
|
|
213
|
+
*/
|
|
214
|
+
decryptMessage(packetJson: string): Promise<string>;
|
|
191
215
|
/**
|
|
192
216
|
* Get encryption/decryption metrics
|
|
193
217
|
*
|
|
@@ -218,4 +242,4 @@ declare class Wolfronix {
|
|
|
218
242
|
*/
|
|
219
243
|
declare function createClient(config: WolfronixConfig | string): Wolfronix;
|
|
220
244
|
|
|
221
|
-
export { type AuthResponse, AuthenticationError, type DeleteResponse, type EncryptResponse, type FileInfo, FileNotFoundError, type ListFilesResponse, type MetricsResponse, NetworkError, PermissionDeniedError, ValidationError, Wolfronix, type WolfronixConfig, WolfronixError, createClient, Wolfronix as default };
|
|
245
|
+
export { type AuthResponse, AuthenticationError, type DeleteResponse, type EncryptMessagePacket, type EncryptResponse, type FileInfo, FileNotFoundError, type ListFilesResponse, type MetricsResponse, NetworkError, PermissionDeniedError, ValidationError, Wolfronix, type WolfronixConfig, WolfronixError, createClient, Wolfronix as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -51,6 +51,11 @@ interface MetricsResponse {
|
|
|
51
51
|
total_bytes_encrypted: number;
|
|
52
52
|
total_bytes_decrypted: number;
|
|
53
53
|
}
|
|
54
|
+
interface EncryptMessagePacket {
|
|
55
|
+
key: string;
|
|
56
|
+
iv: string;
|
|
57
|
+
msg: string;
|
|
58
|
+
}
|
|
54
59
|
declare class WolfronixError extends Error {
|
|
55
60
|
readonly code: string;
|
|
56
61
|
readonly statusCode?: number;
|
|
@@ -188,6 +193,25 @@ declare class Wolfronix {
|
|
|
188
193
|
* ```
|
|
189
194
|
*/
|
|
190
195
|
deleteFile(fileId: string): Promise<DeleteResponse>;
|
|
196
|
+
/**
|
|
197
|
+
* Get another user's public key (for E2E encryption)
|
|
198
|
+
* @param userId The ID of the recipient
|
|
199
|
+
*/
|
|
200
|
+
getPublicKey(userId: string): Promise<string>;
|
|
201
|
+
/**
|
|
202
|
+
* Encrypt a short text message for a recipient (Hybrid Encryption: RSA + AES)
|
|
203
|
+
* Returns a secure JSON string (packet) to send via chat
|
|
204
|
+
*
|
|
205
|
+
* @param text The plain text message
|
|
206
|
+
* @param recipientId The recipient's user ID
|
|
207
|
+
*/
|
|
208
|
+
encryptMessage(text: string, recipientId: string): Promise<string>;
|
|
209
|
+
/**
|
|
210
|
+
* Decrypt a message packet received from chat
|
|
211
|
+
*
|
|
212
|
+
* @param packetJson The secure JSON string packet
|
|
213
|
+
*/
|
|
214
|
+
decryptMessage(packetJson: string): Promise<string>;
|
|
191
215
|
/**
|
|
192
216
|
* Get encryption/decryption metrics
|
|
193
217
|
*
|
|
@@ -218,4 +242,4 @@ declare class Wolfronix {
|
|
|
218
242
|
*/
|
|
219
243
|
declare function createClient(config: WolfronixConfig | string): Wolfronix;
|
|
220
244
|
|
|
221
|
-
export { type AuthResponse, AuthenticationError, type DeleteResponse, type EncryptResponse, type FileInfo, FileNotFoundError, type ListFilesResponse, type MetricsResponse, NetworkError, PermissionDeniedError, ValidationError, Wolfronix, type WolfronixConfig, WolfronixError, createClient, Wolfronix as default };
|
|
245
|
+
export { type AuthResponse, AuthenticationError, type DeleteResponse, type EncryptMessagePacket, type EncryptResponse, type FileInfo, FileNotFoundError, type ListFilesResponse, type MetricsResponse, NetworkError, PermissionDeniedError, ValidationError, Wolfronix, type WolfronixConfig, WolfronixError, createClient, Wolfronix as default };
|
package/dist/index.js
CHANGED
|
@@ -48,6 +48,7 @@ var RSA_ALG = {
|
|
|
48
48
|
hash: "SHA-256"
|
|
49
49
|
};
|
|
50
50
|
var WRAP_ALG = "AES-GCM";
|
|
51
|
+
var SESSION_ALG = "AES-GCM";
|
|
51
52
|
var PBKDF2_ITERATIONS = 1e5;
|
|
52
53
|
async function generateKeyPair() {
|
|
53
54
|
return await getCrypto().subtle.generateKey(
|
|
@@ -150,6 +151,80 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
|
|
|
150
151
|
["decrypt", "unwrapKey"]
|
|
151
152
|
);
|
|
152
153
|
}
|
|
154
|
+
async function generateSessionKey() {
|
|
155
|
+
return await getCrypto().subtle.generateKey(
|
|
156
|
+
{
|
|
157
|
+
name: SESSION_ALG,
|
|
158
|
+
length: 256
|
|
159
|
+
},
|
|
160
|
+
true,
|
|
161
|
+
["encrypt", "decrypt"]
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
async function encryptData(data, key) {
|
|
165
|
+
const enc = new TextEncoder();
|
|
166
|
+
const encodedData = enc.encode(data);
|
|
167
|
+
const iv = getCrypto().getRandomValues(new Uint8Array(12));
|
|
168
|
+
const encryptedContent = await getCrypto().subtle.encrypt(
|
|
169
|
+
{
|
|
170
|
+
name: SESSION_ALG,
|
|
171
|
+
iv
|
|
172
|
+
},
|
|
173
|
+
key,
|
|
174
|
+
encodedData
|
|
175
|
+
);
|
|
176
|
+
return {
|
|
177
|
+
encrypted: arrayBufferToBase64(encryptedContent),
|
|
178
|
+
iv: arrayBufferToBase64(iv.buffer)
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
async function decryptData(encryptedBase64, ivBase64, key) {
|
|
182
|
+
const encryptedData = base64ToArrayBuffer(encryptedBase64);
|
|
183
|
+
const iv = base64ToArrayBuffer(ivBase64);
|
|
184
|
+
const decryptedContent = await getCrypto().subtle.decrypt(
|
|
185
|
+
{
|
|
186
|
+
name: SESSION_ALG,
|
|
187
|
+
iv
|
|
188
|
+
},
|
|
189
|
+
key,
|
|
190
|
+
encryptedData
|
|
191
|
+
);
|
|
192
|
+
const dec = new TextDecoder();
|
|
193
|
+
return dec.decode(decryptedContent);
|
|
194
|
+
}
|
|
195
|
+
async function rsaEncrypt(data, publicKey) {
|
|
196
|
+
const encrypted = await getCrypto().subtle.encrypt(
|
|
197
|
+
{
|
|
198
|
+
name: "RSA-OAEP"
|
|
199
|
+
},
|
|
200
|
+
publicKey,
|
|
201
|
+
data
|
|
202
|
+
);
|
|
203
|
+
return arrayBufferToBase64(encrypted);
|
|
204
|
+
}
|
|
205
|
+
async function rsaDecrypt(encryptedBase64, privateKey) {
|
|
206
|
+
const data = base64ToArrayBuffer(encryptedBase64);
|
|
207
|
+
const decrypted = await getCrypto().subtle.decrypt(
|
|
208
|
+
{
|
|
209
|
+
name: "RSA-OAEP"
|
|
210
|
+
},
|
|
211
|
+
privateKey,
|
|
212
|
+
data
|
|
213
|
+
);
|
|
214
|
+
return decrypted;
|
|
215
|
+
}
|
|
216
|
+
async function exportSessionKey(key) {
|
|
217
|
+
return await getCrypto().subtle.exportKey("raw", key);
|
|
218
|
+
}
|
|
219
|
+
async function importSessionKey(raw) {
|
|
220
|
+
return await getCrypto().subtle.importKey(
|
|
221
|
+
"raw",
|
|
222
|
+
raw,
|
|
223
|
+
SESSION_ALG,
|
|
224
|
+
true,
|
|
225
|
+
["encrypt", "decrypt"]
|
|
226
|
+
);
|
|
227
|
+
}
|
|
153
228
|
function arrayBufferToBase64(buffer) {
|
|
154
229
|
const bytes = new Uint8Array(buffer);
|
|
155
230
|
if (typeof Buffer !== "undefined") {
|
|
@@ -607,6 +682,68 @@ var Wolfronix = class {
|
|
|
607
682
|
}
|
|
608
683
|
return this.request("DELETE", `/api/v1/files/${fileId}`);
|
|
609
684
|
}
|
|
685
|
+
// ============================================================================
|
|
686
|
+
// E2E Chat Encryption Methods
|
|
687
|
+
// ============================================================================
|
|
688
|
+
/**
|
|
689
|
+
* Get another user's public key (for E2E encryption)
|
|
690
|
+
* @param userId The ID of the recipient
|
|
691
|
+
*/
|
|
692
|
+
async getPublicKey(userId) {
|
|
693
|
+
this.ensureAuthenticated();
|
|
694
|
+
const result = await this.request("GET", `/api/v1/keys/${userId}`);
|
|
695
|
+
return result.public_key;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Encrypt a short text message for a recipient (Hybrid Encryption: RSA + AES)
|
|
699
|
+
* Returns a secure JSON string (packet) to send via chat
|
|
700
|
+
*
|
|
701
|
+
* @param text The plain text message
|
|
702
|
+
* @param recipientId The recipient's user ID
|
|
703
|
+
*/
|
|
704
|
+
async encryptMessage(text, recipientId) {
|
|
705
|
+
this.ensureAuthenticated();
|
|
706
|
+
const recipientPubKeyPEM = await this.getPublicKey(recipientId);
|
|
707
|
+
const recipientPubKey = await importKeyFromPEM(recipientPubKeyPEM, "public");
|
|
708
|
+
const sessionKey = await generateSessionKey();
|
|
709
|
+
const { encrypted: encryptedMsg, iv } = await encryptData(text, sessionKey);
|
|
710
|
+
const rawSessionKey = await exportSessionKey(sessionKey);
|
|
711
|
+
const encryptedSessionKey = await rsaEncrypt(rawSessionKey, recipientPubKey);
|
|
712
|
+
const packet = {
|
|
713
|
+
key: encryptedSessionKey,
|
|
714
|
+
iv,
|
|
715
|
+
msg: encryptedMsg
|
|
716
|
+
};
|
|
717
|
+
return JSON.stringify(packet);
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Decrypt a message packet received from chat
|
|
721
|
+
*
|
|
722
|
+
* @param packetJson The secure JSON string packet
|
|
723
|
+
*/
|
|
724
|
+
async decryptMessage(packetJson) {
|
|
725
|
+
this.ensureAuthenticated();
|
|
726
|
+
if (!this.privateKey) {
|
|
727
|
+
throw new Error("Private key not available. Is user logged in?");
|
|
728
|
+
}
|
|
729
|
+
let packet;
|
|
730
|
+
try {
|
|
731
|
+
packet = JSON.parse(packetJson);
|
|
732
|
+
} catch (e) {
|
|
733
|
+
throw new ValidationError("Invalid message packet format");
|
|
734
|
+
}
|
|
735
|
+
if (!packet.key || !packet.iv || !packet.msg) {
|
|
736
|
+
throw new ValidationError("Invalid message packet structure");
|
|
737
|
+
}
|
|
738
|
+
try {
|
|
739
|
+
const rawSessionKey = await rsaDecrypt(packet.key, this.privateKey);
|
|
740
|
+
const sessionKey = await importSessionKey(rawSessionKey);
|
|
741
|
+
const plainText = await decryptData(packet.msg, packet.iv, sessionKey);
|
|
742
|
+
return plainText;
|
|
743
|
+
} catch (error) {
|
|
744
|
+
throw new Error("Decryption failed. You may not be the intended recipient.");
|
|
745
|
+
}
|
|
746
|
+
}
|
|
610
747
|
// ==========================================================================
|
|
611
748
|
// Metrics & Status
|
|
612
749
|
// ==========================================================================
|
package/dist/index.mjs
CHANGED
|
@@ -14,6 +14,7 @@ var RSA_ALG = {
|
|
|
14
14
|
hash: "SHA-256"
|
|
15
15
|
};
|
|
16
16
|
var WRAP_ALG = "AES-GCM";
|
|
17
|
+
var SESSION_ALG = "AES-GCM";
|
|
17
18
|
var PBKDF2_ITERATIONS = 1e5;
|
|
18
19
|
async function generateKeyPair() {
|
|
19
20
|
return await getCrypto().subtle.generateKey(
|
|
@@ -116,6 +117,80 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
|
|
|
116
117
|
["decrypt", "unwrapKey"]
|
|
117
118
|
);
|
|
118
119
|
}
|
|
120
|
+
async function generateSessionKey() {
|
|
121
|
+
return await getCrypto().subtle.generateKey(
|
|
122
|
+
{
|
|
123
|
+
name: SESSION_ALG,
|
|
124
|
+
length: 256
|
|
125
|
+
},
|
|
126
|
+
true,
|
|
127
|
+
["encrypt", "decrypt"]
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
async function encryptData(data, key) {
|
|
131
|
+
const enc = new TextEncoder();
|
|
132
|
+
const encodedData = enc.encode(data);
|
|
133
|
+
const iv = getCrypto().getRandomValues(new Uint8Array(12));
|
|
134
|
+
const encryptedContent = await getCrypto().subtle.encrypt(
|
|
135
|
+
{
|
|
136
|
+
name: SESSION_ALG,
|
|
137
|
+
iv
|
|
138
|
+
},
|
|
139
|
+
key,
|
|
140
|
+
encodedData
|
|
141
|
+
);
|
|
142
|
+
return {
|
|
143
|
+
encrypted: arrayBufferToBase64(encryptedContent),
|
|
144
|
+
iv: arrayBufferToBase64(iv.buffer)
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
async function decryptData(encryptedBase64, ivBase64, key) {
|
|
148
|
+
const encryptedData = base64ToArrayBuffer(encryptedBase64);
|
|
149
|
+
const iv = base64ToArrayBuffer(ivBase64);
|
|
150
|
+
const decryptedContent = await getCrypto().subtle.decrypt(
|
|
151
|
+
{
|
|
152
|
+
name: SESSION_ALG,
|
|
153
|
+
iv
|
|
154
|
+
},
|
|
155
|
+
key,
|
|
156
|
+
encryptedData
|
|
157
|
+
);
|
|
158
|
+
const dec = new TextDecoder();
|
|
159
|
+
return dec.decode(decryptedContent);
|
|
160
|
+
}
|
|
161
|
+
async function rsaEncrypt(data, publicKey) {
|
|
162
|
+
const encrypted = await getCrypto().subtle.encrypt(
|
|
163
|
+
{
|
|
164
|
+
name: "RSA-OAEP"
|
|
165
|
+
},
|
|
166
|
+
publicKey,
|
|
167
|
+
data
|
|
168
|
+
);
|
|
169
|
+
return arrayBufferToBase64(encrypted);
|
|
170
|
+
}
|
|
171
|
+
async function rsaDecrypt(encryptedBase64, privateKey) {
|
|
172
|
+
const data = base64ToArrayBuffer(encryptedBase64);
|
|
173
|
+
const decrypted = await getCrypto().subtle.decrypt(
|
|
174
|
+
{
|
|
175
|
+
name: "RSA-OAEP"
|
|
176
|
+
},
|
|
177
|
+
privateKey,
|
|
178
|
+
data
|
|
179
|
+
);
|
|
180
|
+
return decrypted;
|
|
181
|
+
}
|
|
182
|
+
async function exportSessionKey(key) {
|
|
183
|
+
return await getCrypto().subtle.exportKey("raw", key);
|
|
184
|
+
}
|
|
185
|
+
async function importSessionKey(raw) {
|
|
186
|
+
return await getCrypto().subtle.importKey(
|
|
187
|
+
"raw",
|
|
188
|
+
raw,
|
|
189
|
+
SESSION_ALG,
|
|
190
|
+
true,
|
|
191
|
+
["encrypt", "decrypt"]
|
|
192
|
+
);
|
|
193
|
+
}
|
|
119
194
|
function arrayBufferToBase64(buffer) {
|
|
120
195
|
const bytes = new Uint8Array(buffer);
|
|
121
196
|
if (typeof Buffer !== "undefined") {
|
|
@@ -573,6 +648,68 @@ var Wolfronix = class {
|
|
|
573
648
|
}
|
|
574
649
|
return this.request("DELETE", `/api/v1/files/${fileId}`);
|
|
575
650
|
}
|
|
651
|
+
// ============================================================================
|
|
652
|
+
// E2E Chat Encryption Methods
|
|
653
|
+
// ============================================================================
|
|
654
|
+
/**
|
|
655
|
+
* Get another user's public key (for E2E encryption)
|
|
656
|
+
* @param userId The ID of the recipient
|
|
657
|
+
*/
|
|
658
|
+
async getPublicKey(userId) {
|
|
659
|
+
this.ensureAuthenticated();
|
|
660
|
+
const result = await this.request("GET", `/api/v1/keys/${userId}`);
|
|
661
|
+
return result.public_key;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Encrypt a short text message for a recipient (Hybrid Encryption: RSA + AES)
|
|
665
|
+
* Returns a secure JSON string (packet) to send via chat
|
|
666
|
+
*
|
|
667
|
+
* @param text The plain text message
|
|
668
|
+
* @param recipientId The recipient's user ID
|
|
669
|
+
*/
|
|
670
|
+
async encryptMessage(text, recipientId) {
|
|
671
|
+
this.ensureAuthenticated();
|
|
672
|
+
const recipientPubKeyPEM = await this.getPublicKey(recipientId);
|
|
673
|
+
const recipientPubKey = await importKeyFromPEM(recipientPubKeyPEM, "public");
|
|
674
|
+
const sessionKey = await generateSessionKey();
|
|
675
|
+
const { encrypted: encryptedMsg, iv } = await encryptData(text, sessionKey);
|
|
676
|
+
const rawSessionKey = await exportSessionKey(sessionKey);
|
|
677
|
+
const encryptedSessionKey = await rsaEncrypt(rawSessionKey, recipientPubKey);
|
|
678
|
+
const packet = {
|
|
679
|
+
key: encryptedSessionKey,
|
|
680
|
+
iv,
|
|
681
|
+
msg: encryptedMsg
|
|
682
|
+
};
|
|
683
|
+
return JSON.stringify(packet);
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Decrypt a message packet received from chat
|
|
687
|
+
*
|
|
688
|
+
* @param packetJson The secure JSON string packet
|
|
689
|
+
*/
|
|
690
|
+
async decryptMessage(packetJson) {
|
|
691
|
+
this.ensureAuthenticated();
|
|
692
|
+
if (!this.privateKey) {
|
|
693
|
+
throw new Error("Private key not available. Is user logged in?");
|
|
694
|
+
}
|
|
695
|
+
let packet;
|
|
696
|
+
try {
|
|
697
|
+
packet = JSON.parse(packetJson);
|
|
698
|
+
} catch (e) {
|
|
699
|
+
throw new ValidationError("Invalid message packet format");
|
|
700
|
+
}
|
|
701
|
+
if (!packet.key || !packet.iv || !packet.msg) {
|
|
702
|
+
throw new ValidationError("Invalid message packet structure");
|
|
703
|
+
}
|
|
704
|
+
try {
|
|
705
|
+
const rawSessionKey = await rsaDecrypt(packet.key, this.privateKey);
|
|
706
|
+
const sessionKey = await importSessionKey(rawSessionKey);
|
|
707
|
+
const plainText = await decryptData(packet.msg, packet.iv, sessionKey);
|
|
708
|
+
return plainText;
|
|
709
|
+
} catch (error) {
|
|
710
|
+
throw new Error("Decryption failed. You may not be the intended recipient.");
|
|
711
|
+
}
|
|
712
|
+
}
|
|
576
713
|
// ==========================================================================
|
|
577
714
|
// Metrics & Status
|
|
578
715
|
// ==========================================================================
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wolfronix-sdk",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Official Wolfronix SDK for JavaScript/TypeScript - Zero-knowledge encryption made simple",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -62,4 +62,4 @@
|
|
|
62
62
|
"optional": true
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
}
|
|
65
|
+
}
|