@pulkitsinha007/hybrid-crypto-js 1.2.2 → 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 CHANGED
@@ -90,6 +90,32 @@ import { decryptWithSymmetricKey } from '@pulkitsinha007/hybrid-crypto-js';
90
90
  const data = await decryptWithSymmetricKey({ encryptedData, iv }, sessionKey);
91
91
  ```
92
92
 
93
+ ### `encryptAsymmetric(data, publicKey)`
94
+ Encrypts data directly using an RSA public key.
95
+ - **Parameters**:
96
+ - `data`: `string | object` - The payload to encrypt.
97
+ - `publicKey`: `string` - The RSA public key (Base64).
98
+ - **Returns**: `Promise<string>` (Base64 encoded)
99
+
100
+ ```javascript
101
+ import { encryptAsymmetric } from '@pulkitsinha007/hybrid-crypto-js';
102
+
103
+ const encryptedData = await encryptAsymmetric({ secret: "data" }, publicKey);
104
+ ```
105
+
106
+ ### `decryptAsymmetric(encryptedData, privateKey)`
107
+ Decrypts data directly using an RSA private key.
108
+ - **Parameters**:
109
+ - `encryptedData`: `string` - The encrypted data (Base64).
110
+ - `privateKey`: `string` - The RSA private key (Base64).
111
+ - **Returns**: `Promise<string | object>`
112
+
113
+ ```javascript
114
+ import { decryptAsymmetric } from '@pulkitsinha007/hybrid-crypto-js';
115
+
116
+ const data = await decryptAsymmetric(encryptedData, privateKey);
117
+ ```
118
+
93
119
  ---
94
120
 
95
121
  ## Backend Setup (Dummy Application)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pulkitsinha007/hybrid-crypto-js",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "Hybrid encryption package using native crypto modules for Node and Browser",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/crypto.js CHANGED
@@ -176,4 +176,71 @@ export async function unwrapKey(wrappedKey, privateKey) {
176
176
  );
177
177
 
178
178
  return key;
179
+ }
180
+
181
+ /**
182
+ * Encrypts data directly using an RSA public key (Asymmetric).
183
+ * @param {string|object} data - The payload to encrypt.
184
+ * @param {string} publicKey - The RSA public key (Base64).
185
+ * @returns {Promise<string>} The encrypted data as Base64 string.
186
+ */
187
+ export async function encryptAsymmetric(data, publicKey) {
188
+ const crypto = getCrypto();
189
+ const rsaKeyBuffer = base64ToArrayBuffer(publicKey);
190
+ const rsaPublicKey = await crypto.subtle.importKey(
191
+ "spki",
192
+ rsaKeyBuffer,
193
+ RSA_ALGO,
194
+ false,
195
+ ["encrypt"]
196
+ );
197
+
198
+ const payloadStr = typeof data === 'object' ? JSON.stringify(data) : String(data);
199
+ const payloadBuffer = str2ab(payloadStr);
200
+
201
+ const encryptedBuffer = await crypto.subtle.encrypt(
202
+ {
203
+ name: "RSA-OAEP"
204
+ },
205
+ rsaPublicKey,
206
+ payloadBuffer
207
+ );
208
+
209
+ return arrayBufferToBase64(encryptedBuffer);
210
+ }
211
+
212
+ /**
213
+ * Decrypts data directly using an RSA private key (Asymmetric).
214
+ * @param {string} encryptedData - The encrypted data (Base64).
215
+ * @param {string} privateKey - The RSA private key (Base64).
216
+ * @returns {Promise<string|object>} The decrypted payload.
217
+ */
218
+ export async function decryptAsymmetric(encryptedData, privateKey) {
219
+ const crypto = getCrypto();
220
+ const rsaKeyBuffer = base64ToArrayBuffer(privateKey);
221
+ const rsaPrivateKey = await crypto.subtle.importKey(
222
+ "pkcs8",
223
+ rsaKeyBuffer,
224
+ RSA_ALGO,
225
+ false,
226
+ ["decrypt"]
227
+ );
228
+
229
+ const encryptedBuffer = base64ToArrayBuffer(encryptedData);
230
+
231
+ const decryptedBuffer = await crypto.subtle.decrypt(
232
+ {
233
+ name: "RSA-OAEP"
234
+ },
235
+ rsaPrivateKey,
236
+ encryptedBuffer
237
+ );
238
+
239
+ const payloadStr = ab2str(decryptedBuffer);
240
+
241
+ try {
242
+ return JSON.parse(payloadStr);
243
+ } catch (e) {
244
+ return payloadStr;
245
+ }
179
246
  }
package/src/index.d.ts CHANGED
@@ -91,4 +91,20 @@ export function wrapKey(key: CryptoKey, publicKey: string): Promise<string>;
91
91
  * @param privateKey - The RSA private key (Base64).
92
92
  * @returns The unwrapped AES key.
93
93
  */
94
- export function unwrapKey(wrappedKey: string, privateKey: string): Promise<CryptoKey>;
94
+ export function unwrapKey(wrappedKey: string, privateKey: string): Promise<CryptoKey>;
95
+
96
+ /**
97
+ * Encrypts data directly using an RSA public key (Asymmetric).
98
+ * @param data - The payload to encrypt.
99
+ * @param publicKey - The RSA public key (Base64).
100
+ * @returns The encrypted data as Base64 string.
101
+ */
102
+ export function encryptAsymmetric(data: string | object, publicKey: string): Promise<string>;
103
+
104
+ /**
105
+ * Decrypts data directly using an RSA private key (Asymmetric).
106
+ * @param encryptedData - The encrypted data (Base64).
107
+ * @param privateKey - The RSA private key (Base64).
108
+ * @returns The decrypted payload.
109
+ */
110
+ export function decryptAsymmetric<T = any>(encryptedData: string, privateKey: string): Promise<T>;
package/src/index.js CHANGED
@@ -4,6 +4,8 @@ export {
4
4
  encryptWithSymmetricKey,
5
5
  decryptWithSymmetricKey,
6
6
  wrapKey,
7
- unwrapKey
7
+ unwrapKey,
8
+ encryptAsymmetric,
9
+ decryptAsymmetric
8
10
  } from './crypto.js';
9
11
  export * from './utils.js';
package/src/utils.js CHANGED
@@ -1,77 +1,77 @@
1
- // Utility functions for Hybrid Crypto Package
2
-
3
- /**
4
- * Converts a string to an ArrayBuffer using TextEncoder.
5
- * @param {string} str - The string to convert.
6
- * @returns {ArrayBuffer} The resulting ArrayBuffer.
7
- */
8
- export function str2ab(str) {
9
- return new TextEncoder().encode(str);
10
- }
11
-
12
- /**
13
- * Converts an ArrayBuffer to a string using TextDecoder.
14
- * @param {ArrayBuffer} buf - The buffer to convert.
15
- * @returns {string} The resulting string.
16
- */
17
- export function ab2str(buf) {
18
- return new TextDecoder().decode(buf);
19
- }
20
-
21
- /**
22
- * Converts an ArrayBuffer to a Base64 string.
23
- * @param {ArrayBuffer} buf - The buffer to convert.
24
- * @returns {string} Base64 string.
25
- */
26
- export function arrayBufferToBase64(buf) {
27
- let binary = '';
28
- const bytes = new Uint8Array(buf);
29
- const len = bytes.byteLength;
30
- for (let i = 0; i < len; i++) {
31
- binary += String.fromCharCode(bytes[i]);
32
- }
33
- return btoa(binary);
34
- }
35
-
36
- /**
37
- * Converts a Base64 string to an ArrayBuffer.
38
- * @param {string} base64 - The Base64 string.
39
- * @returns {ArrayBuffer} The resulting ArrayBuffer.
40
- */
41
- export function base64ToArrayBuffer(base64) {
42
- const binaryString = atob(base64);
43
- const len = binaryString.length;
44
- const bytes = new Uint8Array(len);
45
- for (let i = 0; i < len; i++) {
46
- bytes[i] = binaryString.charCodeAt(i);
47
- }
48
- return bytes.buffer;
49
- }
50
-
51
- /**
52
- * Converts a PEM formatted string to an ArrayBuffer.
53
- * @param {string} pem - The PEM string.
54
- * @returns {ArrayBuffer} The raw key data.
55
- */
56
- export function pemToArrayBuffer(pem) {
57
- // Remove headers, footers, and newlines
58
- const b64 = pem
59
- .replace(/-----BEGIN [^-]+-----/, '')
60
- .replace(/-----END [^-]+-----/, '')
61
- .replace(/\s/g, ''); // Removes all whitespace including newlines
62
- return base64ToArrayBuffer(b64);
63
- }
64
-
65
- /**
66
- * Converts an ArrayBuffer to a PEM formatted string.
67
- * @param {ArrayBuffer} buf - The raw key data.
68
- * @param {string} type - The key type (e.g., 'PUBLIC KEY', 'PRIVATE KEY').
69
- * @returns {string} The PEM string.
70
- */
71
- export function arrayBufferToPem(buf, type) {
72
- const b64 = arrayBufferToBase64(buf);
73
- const pemString = `-----BEGIN ${type}-----\n` +
74
- b64.match(/.{1,64}/g).join('\n') +
75
- `\n-----END ${type}-----\n`;
76
- return pemString;
77
- }
1
+ // Utility functions for Hybrid Crypto Package
2
+
3
+ /**
4
+ * Converts a string to an ArrayBuffer using TextEncoder.
5
+ * @param {string} str - The string to convert.
6
+ * @returns {ArrayBuffer} The resulting ArrayBuffer.
7
+ */
8
+ export function str2ab(str) {
9
+ return new TextEncoder().encode(str);
10
+ }
11
+
12
+ /**
13
+ * Converts an ArrayBuffer to a string using TextDecoder.
14
+ * @param {ArrayBuffer} buf - The buffer to convert.
15
+ * @returns {string} The resulting string.
16
+ */
17
+ export function ab2str(buf) {
18
+ return new TextDecoder().decode(buf);
19
+ }
20
+
21
+ /**
22
+ * Converts an ArrayBuffer to a Base64 string.
23
+ * @param {ArrayBuffer} buf - The buffer to convert.
24
+ * @returns {string} Base64 string.
25
+ */
26
+ export function arrayBufferToBase64(buf) {
27
+ let binary = '';
28
+ const bytes = new Uint8Array(buf);
29
+ const len = bytes.byteLength;
30
+ for (let i = 0; i < len; i++) {
31
+ binary += String.fromCharCode(bytes[i]);
32
+ }
33
+ return btoa(binary);
34
+ }
35
+
36
+ /**
37
+ * Converts a Base64 string to an ArrayBuffer.
38
+ * @param {string} base64 - The Base64 string.
39
+ * @returns {ArrayBuffer} The resulting ArrayBuffer.
40
+ */
41
+ export function base64ToArrayBuffer(base64) {
42
+ const binaryString = atob(base64);
43
+ const len = binaryString.length;
44
+ const bytes = new Uint8Array(len);
45
+ for (let i = 0; i < len; i++) {
46
+ bytes[i] = binaryString.charCodeAt(i);
47
+ }
48
+ return bytes.buffer;
49
+ }
50
+
51
+ /**
52
+ * Converts a PEM formatted string to an ArrayBuffer.
53
+ * @param {string} pem - The PEM string.
54
+ * @returns {ArrayBuffer} The raw key data.
55
+ */
56
+ export function pemToArrayBuffer(pem) {
57
+ // Remove headers, footers, and newlines
58
+ const b64 = pem
59
+ .replace(/-----BEGIN [^-]+-----/, '')
60
+ .replace(/-----END [^-]+-----/, '')
61
+ .replace(/\s/g, ''); // Removes all whitespace including newlines
62
+ return base64ToArrayBuffer(b64);
63
+ }
64
+
65
+ /**
66
+ * Converts an ArrayBuffer to a PEM formatted string.
67
+ * @param {ArrayBuffer} buf - The raw key data.
68
+ * @param {string} type - The key type (e.g., 'PUBLIC KEY', 'PRIVATE KEY').
69
+ * @returns {string} The PEM string.
70
+ */
71
+ export function arrayBufferToPem(buf, type) {
72
+ const b64 = arrayBufferToBase64(buf);
73
+ const pemString = `-----BEGIN ${type}-----\n` +
74
+ b64.match(/.{1,64}/g).join('\n') +
75
+ `\n-----END ${type}-----\n`;
76
+ return pemString;
77
+ }
@@ -0,0 +1,43 @@
1
+ import { test, describe, it } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import {
4
+ generateKeyPair,
5
+ encryptAsymmetric,
6
+ decryptAsymmetric
7
+ } from '../src/index.js';
8
+
9
+ describe('Asymmetric Encryption (RSA-OAEP)', () => {
10
+ it('should encrypt and decrypt a plain string', async () => {
11
+ const { publicKey, privateKey } = await generateKeyPair();
12
+ const originalData = "Hello, Asymmetric World!";
13
+
14
+ const encryptedData = await encryptAsymmetric(originalData, publicKey);
15
+ assert.notStrictEqual(encryptedData, originalData);
16
+
17
+ const decryptedData = await decryptAsymmetric(encryptedData, privateKey);
18
+ assert.strictEqual(decryptedData, originalData);
19
+ });
20
+
21
+ it('should encrypt and decrypt a JSON object', async () => {
22
+ const { publicKey, privateKey } = await generateKeyPair();
23
+ const originalData = { foo: "bar", baz: 123 };
24
+
25
+ const encryptedData = await encryptAsymmetric(originalData, publicKey);
26
+ const decryptedData = await decryptAsymmetric(encryptedData, privateKey);
27
+
28
+ assert.deepStrictEqual(decryptedData, originalData);
29
+ });
30
+
31
+ it('should fail to decrypt with the wrong private key', async () => {
32
+ const keys1 = await generateKeyPair();
33
+ const keys2 = await generateKeyPair();
34
+
35
+ const originalData = "Secret message";
36
+ const encryptedData = await encryptAsymmetric(originalData, keys1.publicKey);
37
+
38
+ await assert.rejects(
39
+ () => decryptAsymmetric(encryptedData, keys2.privateKey),
40
+ /OperationError|DataError/
41
+ );
42
+ });
43
+ });