@nr1e/commons 0.0.0-snapshot-20251228031344 → 0.0.0-snapshot-20251228033901
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/encryption/crypto-generator.d.mts +3 -0
- package/dist/encryption/crypto-generator.d.mts.map +1 -0
- package/dist/encryption/crypto-generator.mjs +8 -0
- package/dist/encryption/crypto-generator.mjs.map +1 -0
- package/dist/encryption/crypto-generator.test.d.mts +2 -0
- package/dist/encryption/crypto-generator.test.d.mts.map +1 -0
- package/dist/encryption/crypto-generator.test.mjs +13 -0
- package/dist/encryption/crypto-generator.test.mjs.map +1 -0
- package/dist/encryption/encryption.d.mts +11 -0
- package/dist/encryption/encryption.d.mts.map +1 -0
- package/dist/encryption/encryption.mjs +47 -0
- package/dist/encryption/encryption.mjs.map +1 -0
- package/dist/encryption/encryption.test.d.mts +2 -0
- package/dist/encryption/encryption.test.d.mts.map +1 -0
- package/dist/encryption/encryption.test.mjs +19 -0
- package/dist/encryption/encryption.test.mjs.map +1 -0
- package/dist/encryption/index.d.mts +4 -0
- package/dist/encryption/index.d.mts.map +1 -0
- package/dist/encryption/index.mjs +4 -0
- package/dist/encryption/index.mjs.map +1 -0
- package/dist/encryption/new-format.test.d.mts +2 -0
- package/dist/encryption/new-format.test.d.mts.map +1 -0
- package/dist/encryption/new-format.test.mjs +127 -0
- package/dist/encryption/new-format.test.mjs.map +1 -0
- package/dist/encryption/rsa-encryption.browser.d.mts +36 -0
- package/dist/encryption/rsa-encryption.browser.d.mts.map +1 -0
- package/dist/encryption/rsa-encryption.browser.mjs +140 -0
- package/dist/encryption/rsa-encryption.browser.mjs.map +1 -0
- package/dist/encryption/rsa-encryption.d.mts +89 -0
- package/dist/encryption/rsa-encryption.d.mts.map +1 -0
- package/dist/encryption/rsa-encryption.mjs +254 -0
- package/dist/encryption/rsa-encryption.mjs.map +1 -0
- package/dist/encryption/rsa-encryption.test.d.mts +2 -0
- package/dist/encryption/rsa-encryption.test.d.mts.map +1 -0
- package/dist/encryption/rsa-encryption.test.mjs +324 -0
- package/dist/encryption/rsa-encryption.test.mjs.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-generator.d.mts","sourceRoot":"","sources":["../../src/encryption/crypto-generator.mts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAEtD;AAED,wBAAgB,cAAc,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAE1D"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { randomBytes } from 'crypto';
|
|
2
|
+
export function generateId(length = 16) {
|
|
3
|
+
return randomBytes(length).toString('base64url');
|
|
4
|
+
}
|
|
5
|
+
export function generateApiKey(length = 32) {
|
|
6
|
+
return randomBytes(length).toString('base64url');
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=crypto-generator.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-generator.mjs","sourceRoot":"","sources":["../../src/encryption/crypto-generator.mts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,QAAQ,CAAC;AAEnC,MAAM,UAAU,UAAU,CAAC,SAAiB,EAAE;IAC5C,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE;IAChD,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-generator.test.d.mts","sourceRoot":"","sources":["../../src/encryption/crypto-generator.test.mts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import { generateApiKey, generateId } from './crypto-generator.mjs';
|
|
3
|
+
test('generateId', () => {
|
|
4
|
+
const id = generateId();
|
|
5
|
+
console.log(id);
|
|
6
|
+
expect(id.length).toBe(22);
|
|
7
|
+
});
|
|
8
|
+
test('Test generateApiKey', () => {
|
|
9
|
+
const apiKey = generateApiKey();
|
|
10
|
+
console.log(apiKey);
|
|
11
|
+
expect(apiKey).toBeDefined();
|
|
12
|
+
}, 10000);
|
|
13
|
+
//# sourceMappingURL=crypto-generator.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-generator.test.mjs","sourceRoot":"","sources":["../../src/encryption/crypto-generator.test.mts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,MAAM,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAC,cAAc,EAAE,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAElE,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE;IACtB,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE;IAC/B,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;AAC/B,CAAC,EAAE,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
+
export declare function localEncrypt(val: object, key: Buffer | string): string;
|
|
4
|
+
export declare function localDecrypt(encrypted: string, key: Buffer | string): any;
|
|
5
|
+
export declare function generateKey(size?: number): Buffer;
|
|
6
|
+
export declare function generateEncodedKey(size?: number): string;
|
|
7
|
+
export declare function generateIV(size?: number): Buffer;
|
|
8
|
+
export declare function generateEncodedIV(size?: number): string;
|
|
9
|
+
export declare function decodeKey(encodedKey: string): Buffer;
|
|
10
|
+
export declare function decodeIV(encodedIV: string): Buffer;
|
|
11
|
+
//# sourceMappingURL=encryption.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.d.mts","sourceRoot":"","sources":["../../src/encryption/encryption.mts"],"names":[],"mappings":";;AAMA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,UAS7D;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,OAanE;AAED,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,UAExC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,MAAM,UAE/C;AAED,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,UAEvC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,UAE9C;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,UAE3C;AAED,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,UAEzC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv } from 'crypto';
|
|
2
|
+
import { randomBytes } from 'node:crypto';
|
|
3
|
+
const ALGORITHM = 'aes-128-cbc';
|
|
4
|
+
const SEPARATOR = '|';
|
|
5
|
+
export function localEncrypt(val, key) {
|
|
6
|
+
if (typeof key === 'string') {
|
|
7
|
+
key = decodeKey(key);
|
|
8
|
+
}
|
|
9
|
+
const iv = generateIV();
|
|
10
|
+
const cipher = createCipheriv(ALGORITHM, key, iv);
|
|
11
|
+
let encrypted = cipher.update(JSON.stringify(val), 'utf8', 'base64url');
|
|
12
|
+
encrypted += cipher.final('base64url');
|
|
13
|
+
return iv.toString('base64url') + SEPARATOR + encrypted;
|
|
14
|
+
}
|
|
15
|
+
export function localDecrypt(encrypted, key) {
|
|
16
|
+
if (typeof key === 'string') {
|
|
17
|
+
key = decodeKey(key);
|
|
18
|
+
}
|
|
19
|
+
const parts = encrypted.split(SEPARATOR);
|
|
20
|
+
if (parts.length !== 2) {
|
|
21
|
+
throw new Error('Invalid encrypted value');
|
|
22
|
+
}
|
|
23
|
+
const iv = decodeIV(parts[0]);
|
|
24
|
+
encrypted = parts[1];
|
|
25
|
+
const decipher = createDecipheriv(ALGORITHM, key, iv);
|
|
26
|
+
const decrypted = decipher.update(encrypted, 'base64url', 'utf8');
|
|
27
|
+
return JSON.parse(decrypted + decipher.final('utf8'));
|
|
28
|
+
}
|
|
29
|
+
export function generateKey(size) {
|
|
30
|
+
return randomBytes(size ?? 16);
|
|
31
|
+
}
|
|
32
|
+
export function generateEncodedKey(size) {
|
|
33
|
+
return generateKey(size).toString('base64');
|
|
34
|
+
}
|
|
35
|
+
export function generateIV(size) {
|
|
36
|
+
return randomBytes(size ?? 16);
|
|
37
|
+
}
|
|
38
|
+
export function generateEncodedIV(size) {
|
|
39
|
+
return generateIV(size).toString('base64');
|
|
40
|
+
}
|
|
41
|
+
export function decodeKey(encodedKey) {
|
|
42
|
+
return Buffer.from(encodedKey, 'base64');
|
|
43
|
+
}
|
|
44
|
+
export function decodeIV(encodedIV) {
|
|
45
|
+
return Buffer.from(encodedIV, 'base64');
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=encryption.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.mjs","sourceRoot":"","sources":["../../src/encryption/encryption.mts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAE,gBAAgB,EAAC,MAAM,QAAQ,CAAC;AACxD,OAAO,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAExC,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,SAAS,GAAG,GAAG,CAAC;AAEtB,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,GAAoB;IAC5D,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAClD,IAAI,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IACxE,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACvC,OAAO,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,SAAS,GAAG,SAAS,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAiB,EAAE,GAAoB;IAClE,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACrB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IAClE,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAa;IACvC,OAAO,WAAW,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAa;IAC9C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,WAAW,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAa;IAC7C,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,UAAkB;IAC1C,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,SAAiB;IACxC,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.test.d.mts","sourceRoot":"","sources":["../../src/encryption/encryption.test.mts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
import { decodeKey, generateEncodedKey, localDecrypt, localEncrypt, } from './encryption.mjs';
|
|
3
|
+
test('Test generateEncodedKey', () => {
|
|
4
|
+
const key = generateEncodedKey();
|
|
5
|
+
expect(key).toBeDefined();
|
|
6
|
+
console.log('Encoded key:', key);
|
|
7
|
+
const decoded = decodeKey(key);
|
|
8
|
+
expect(decoded).toBeDefined();
|
|
9
|
+
}, 10000);
|
|
10
|
+
test('Test encryption', () => {
|
|
11
|
+
const key = generateEncodedKey();
|
|
12
|
+
const encrypted = localEncrypt({ test: 'test' }, decodeKey(key));
|
|
13
|
+
expect(encrypted).toBeDefined();
|
|
14
|
+
console.log('Encrypted:', encrypted);
|
|
15
|
+
const decrypted = localDecrypt(encrypted, key);
|
|
16
|
+
expect(decrypted).toBeDefined();
|
|
17
|
+
expect(decrypted).toEqual({ test: 'test' });
|
|
18
|
+
}, 10000);
|
|
19
|
+
//# sourceMappingURL=encryption.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.test.mjs","sourceRoot":"","sources":["../../src/encryption/encryption.test.mts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,MAAM,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,YAAY,EACZ,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACnC,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;IACjC,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC,EAAE,KAAK,CAAC,CAAC;AAEV,IAAI,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC3B,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,YAAY,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAChC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;AAC5C,CAAC,EAAE,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/encryption/index.mts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/encryption/index.mts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-format.test.d.mts","sourceRoot":"","sources":["../../src/encryption/new-format.test.mts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { encryptWithPublicKey, decryptWithPrivateKey, isValidPublicKey, isValidPrivateKey, } from './rsa-encryption.mjs';
|
|
3
|
+
describe('New Environment Format Support', () => {
|
|
4
|
+
// Test keys from the dev environment (raw base64 without PEM headers)
|
|
5
|
+
const rawPublicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1M6wSqLb6VDlo1E1zQet/F8ubAhvdcLLe8CKd66w154qZ4b0mYNSmw7DXR+wNz4k8VkP9Cxi/SxxHqj+PLYugHWftN/OFsSUASWRr0jiywQ5pbEngMU56Wy90iZmu9ngimdwinmuOjIuDFVyQNGb8E9k1YcTUMqhbgV7OPjn2n6YuJje5A/bLXzrF9qwXxDlLz3Idc8oRDjL42/erifhV7jPk6yFGD7TxHYAtaFP9Q6sQzNvPX3z4xJkTsRCDoFXGu5jCWxWKtXZTT7Jgpxo5PWjR05aNSQu87UBDNM1a3cJygFGdi4k9lhVfK9NRLwX3IrGJx0EYpS70e6SYwmxawIDAQAB';
|
|
6
|
+
const rawPrivateKey = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDUzrBKotvpUOWjUTXNB638Xy5sCG91wst7wIp3rrDXnipnhvSZg1KbDsNdH7A3PiTxWQ/0LGL9LHEeqP48ti6AdZ+0384WxJQBJZGvSOLLBDmlsSeAxTnpbL3SJma72eCKZ3CKea46Mi4MVXJA0ZvwT2TVhxNQyqFuBXs4+Ofafpi4mN7kD9stfOsX2rBfEOUvPch1zyhEOMvjb96uJ+FXuM+TrIUYPtPEdgC1oU/1DqxDM289ffPjEmROxEIOgVca7mMJbFYq1dlNPsmCnGjk9aNHTlo1JC7ztQEM0zVrdwnKAUZ2LiT2WFV8r01EvBfcisYnHQRilLvR7pJjCbFrAgMBAAECggEAFNVnTOdEwEK7OJHqwnfOALcQxGLPBqhbY3ImHDFt/q3tWNVNfPnuTF/VoHhJuB7NXxNpDG6MAl0ndej1etwbEVhymjKO6ou0MaiL6q0oBtgTDLWbOHAWi1OqAbjgteNOqD4YNnZTKD9hYrO6y725ln0vUfg3W+F6jFrdBWbYy/sLFC6LiPjBo5UrtYwsFXS63JiOs+wuZGRWDlaOpA26ptGQFh4hIoQ494Lwz5G92w0zKTPh1qGLa+vpB9NlUWpJdZPVbN3GL7q3/N2qwt26VwgR2UB/wdM7lA7m4OltqcYykz8bJa+dm9U/qwME3i7GGhqtSml6ugWE7XsBK47QgQKBgQD2RNK7EnhTKs08j5O8+yLR9ZTFdKsmx6kdXddQ9v//y5IxlYeoQDZ+o6pyWdLixfWg6O4ipMlG+5WOG5Gvxqf/avpUc25aCF157dLLaagDUCoJbsmnw13vDl/xE4HfADJSk8vlhU2MX6z+uYR7t286HbJ9Z0XZnDAo55qoPV0SlwKBgQDdN2FIi9Wr6D1vioQsJLINbTwIQIv5Khko/RzS4MwApdaKiL+0mUFUqPBAX4jxdihv9wl8shtgZZleB+283JzmDouO4I7H4pf8HhQ6Fg/1q66EucgCJvY7xkVN6BGN1RblcDx3GAdoQF7o8k1ME9uynkFTZjGdjEnNh2C8jwL2TQKBgEuy8hfA4K2n3Xh9JcuUYqqpU3aymx2LiAdX3iSsGBrXx3NoZE+qlVWuF2mZBMLiWNOCZhjOEHS6Rsls3gZrCR7xEku9Q7F3Gsys9vvB2XxTOui1XlUsL4aZI5KmDWiv1cgeWDGQHTtF+ZY/DmM9CnqRwFjd0tHGOeOI9bg7TI23AoGBANk9dGzQ3fGm7QYnqirLkos69ZRJBuyWmgS1pGO23L/aHDkJl/Gb+xtPmDgvWYV+erGRkSCCq/3baGR+Nsqcf/ww1n5mKfFDpeuyAj0Uw3GHuqee5jqu1mrXB+I8/1ggpg6FTOvLjiKj7FCo+p22dq8PWKm1Fw5X4XZT9vzVGJyVAoGAfWcHjfYtBZF7j7V1AorL6mDaD7fpDEl/JQxwYpFwryAtSlPFrylXvvxb0R9h2cGdknNSAZhUkl+D+ceIH9iz3mwHT7uncNqwyi7OomOJSeWbsisw2II8vmGdSnEQDKKwZAfJ6nF8BGq6+HuRzD/Y0sujE31CSkRJbMRRgUVmPfU=';
|
|
7
|
+
describe('Key Validation', () => {
|
|
8
|
+
it('should validate raw base64 public key', () => {
|
|
9
|
+
expect(isValidPublicKey(rawPublicKey)).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
it('should validate raw base64 private key', () => {
|
|
12
|
+
expect(isValidPrivateKey(rawPrivateKey)).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
describe('Encryption/Decryption with Raw Base64 Keys', () => {
|
|
16
|
+
it('should encrypt and decrypt a string with raw base64 keys', () => {
|
|
17
|
+
const originalData = 'Test data for new environment format';
|
|
18
|
+
const encrypted = encryptWithPublicKey(originalData, rawPublicKey);
|
|
19
|
+
expect(encrypted).toBeDefined();
|
|
20
|
+
expect(encrypted).not.toBe(originalData);
|
|
21
|
+
const decrypted = decryptWithPrivateKey(encrypted, rawPrivateKey);
|
|
22
|
+
expect(decrypted).toBe(originalData);
|
|
23
|
+
});
|
|
24
|
+
it('should encrypt and decrypt an object with raw base64 keys', () => {
|
|
25
|
+
const originalData = {
|
|
26
|
+
userId: '12345',
|
|
27
|
+
email: 'test@example.com',
|
|
28
|
+
ssn: '123456789',
|
|
29
|
+
};
|
|
30
|
+
const encrypted = encryptWithPublicKey(originalData, rawPublicKey);
|
|
31
|
+
expect(encrypted).toBeDefined();
|
|
32
|
+
const decrypted = decryptWithPrivateKey(encrypted, rawPrivateKey);
|
|
33
|
+
expect(decrypted).toEqual(originalData);
|
|
34
|
+
});
|
|
35
|
+
it('should handle SSN encryption/decryption', () => {
|
|
36
|
+
const ssn = '123456789';
|
|
37
|
+
const encrypted = encryptWithPublicKey(ssn, rawPublicKey);
|
|
38
|
+
const decrypted = decryptWithPrivateKey(encrypted, rawPrivateKey);
|
|
39
|
+
// When a string contains only numbers, JSON.parse converts it to a number
|
|
40
|
+
// Convert back to string for comparison
|
|
41
|
+
expect(String(decrypted)).toBe(ssn);
|
|
42
|
+
});
|
|
43
|
+
it('should handle routing number encryption/decryption', () => {
|
|
44
|
+
const routingNumber = '123456789';
|
|
45
|
+
const encrypted = encryptWithPublicKey(routingNumber, rawPublicKey);
|
|
46
|
+
const decrypted = decryptWithPrivateKey(encrypted, rawPrivateKey);
|
|
47
|
+
// When a string contains only numbers, JSON.parse converts it to a number
|
|
48
|
+
// Convert back to string for comparison
|
|
49
|
+
expect(String(decrypted)).toBe(routingNumber);
|
|
50
|
+
});
|
|
51
|
+
it('should handle account number encryption/decryption', () => {
|
|
52
|
+
const accountNumber = '12345678901234';
|
|
53
|
+
const encrypted = encryptWithPublicKey(accountNumber, rawPublicKey);
|
|
54
|
+
const decrypted = decryptWithPrivateKey(encrypted, rawPrivateKey);
|
|
55
|
+
// When a string contains only numbers, JSON.parse converts it to a number
|
|
56
|
+
// Convert back to string for comparison
|
|
57
|
+
expect(String(decrypted)).toBe(accountNumber);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('Backward Compatibility', () => {
|
|
61
|
+
it('should still work with PEM format keys', () => {
|
|
62
|
+
const pemPublicKey = `-----BEGIN PUBLIC KEY-----
|
|
63
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1M6wSqLb6VDlo1E1zQet
|
|
64
|
+
/F8ubAhvdcLLe8CKd66w154qZ4b0mYNSmw7DXR+wNz4k8VkP9Cxi/SxxHqj+PLYu
|
|
65
|
+
gHWftN/OFsSUASWRr0jiywQ5pbEngMU56Wy90iZmu9ngimdwinmuOjIuDFVyQNGb
|
|
66
|
+
8E9k1YcTUMqhbgV7OPjn2n6YuJje5A/bLXzrF9qwXxDlLz3Idc8oRDjL42/erifh
|
|
67
|
+
V7jPk6yFGD7TxHYAtaFP9Q6sQzNvPX3z4xJkTsRCDoFXGu5jCWxWKtXZTT7Jgpxo
|
|
68
|
+
5PWjR05aNSQu87UBDNM1a3cJygFGdi4k9lhVfK9NRLwX3IrGJx0EYpS70e6SYwmx
|
|
69
|
+
awIDAQAB
|
|
70
|
+
-----END PUBLIC KEY-----`;
|
|
71
|
+
const pemPrivateKey = `-----BEGIN PRIVATE KEY-----
|
|
72
|
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDUzrBKotvpUOWj
|
|
73
|
+
UTXNB638Xy5sCG91wst7wIp3rrDXnipnhvSZg1KbDsNdH7A3PiTxWQ/0LGL9LHEe
|
|
74
|
+
qP48ti6AdZ+0384WxJQBJZGvSOLLBDmlsSeAxTnpbL3SJma72eCKZ3CKea46Mi4M
|
|
75
|
+
VXJA0ZvwT2TVhxNQyqFuBXs4+Ofafpi4mN7kD9stfOsX2rBfEOUvPch1zyhEOMvj
|
|
76
|
+
b96uJ+FXuM+TrIUYPtPEdgC1oU/1DqxDM289ffPjEmROxEIOgVca7mMJbFYq1dlN
|
|
77
|
+
PsmCnGjk9aNHTlo1JC7ztQEM0zVrdwnKAUZ2LiT2WFV8r01EvBfcisYnHQRilLvR
|
|
78
|
+
7pJjCbFrAgMBAAECggEAFNVnTOdEwEK7OJHqwnfOALcQxGLPBqhbY3ImHDFt/q3t
|
|
79
|
+
WNVNfPnuTF/VoHhJuB7NXxNpDG6MAl0ndej1etwbEVhymjKO6ou0MaiL6q0oBtgT
|
|
80
|
+
DLWbOHAWi1OqAbjgteNOqD4YNnZTKD9hYrO6y725ln0vUfg3W+F6jFrdBWbYy/sL
|
|
81
|
+
FC6LiPjBo5UrtYwsFXS63JiOs+wuZGRWDlaOpA26ptGQFh4hIoQ494Lwz5G92w0z
|
|
82
|
+
KTPh1qGLa+vpB9NlUWpJdZPVbN3GL7q3/N2qwt26VwgR2UB/wdM7lA7m4OltqcYy
|
|
83
|
+
kz8bJa+dm9U/qwME3i7GGhqtSml6ugWE7XsBK47QgQKBgQD2RNK7EnhTKs08j5O8
|
|
84
|
+
+yLR9ZTFdKsmx6kdXddQ9v//y5IxlYeoQDZ+o6pyWdLixfWg6O4ipMlG+5WOG5Gv
|
|
85
|
+
xqf/avpUc25aCF157dLLaagDUCoJbsmnw13vDl/xE4HfADJSk8vlhU2MX6z+uYR7
|
|
86
|
+
t286HbJ9Z0XZnDAo55qoPV0SlwKBgQDdN2FIi9Wr6D1vioQsJLINbTwIQIv5Khko
|
|
87
|
+
/RzS4MwApdaKiL+0mUFUqPBAX4jxdihv9wl8shtgZZleB+283JzmDouO4I7H4pf8
|
|
88
|
+
HhQ6Fg/1q66EucgCJvY7xkVN6BGN1RblcDx3GAdoQF7o8k1ME9uynkFTZjGdjEnN
|
|
89
|
+
h2C8jwL2TQKBgEuy8hfA4K2n3Xh9JcuUYqqpU3aymx2LiAdX3iSsGBrXx3NoZE+q
|
|
90
|
+
lVWuF2mZBMLiWNOCZhjOEHS6Rsls3gZrCR7xEku9Q7F3Gsys9vvB2XxTOui1XlUs
|
|
91
|
+
L4aZI5KmDWiv1cgeWDGQHTtF+ZY/DmM9CnqRwFjd0tHGOeOI9bg7TI23AoGBANk9
|
|
92
|
+
dGzQ3fGm7QYnqirLkos69ZRJBuyWmgS1pGO23L/aHDkJl/Gb+xtPmDgvWYV+erGR
|
|
93
|
+
kSCCq/3baGR+Nsqcf/ww1n5mKfFDpeuyAj0Uw3GHuqee5jqu1mrXB+I8/1ggpg6F
|
|
94
|
+
TOvLjiKj7FCo+p22dq8PWKm1Fw5X4XZT9vzVGJyVAoGAfWcHjfYtBZF7j7V1AorL
|
|
95
|
+
6mDaD7fpDEl/JQxwYpFwryAtSlPFrylXvvxb0R9h2cGdknNSAZhUkl+D+ceIH9iz
|
|
96
|
+
3mwHT7uncNqwyi7OomOJSeWbsisw2II8vmGdSnEQDKKwZAfJ6nF8BGq6+HuRzD/Y
|
|
97
|
+
0sujE31CSkRJbMRRgUVmPfU=
|
|
98
|
+
-----END PRIVATE KEY-----`;
|
|
99
|
+
const testData = 'Test with PEM format';
|
|
100
|
+
const encrypted = encryptWithPublicKey(testData, pemPublicKey);
|
|
101
|
+
const decrypted = decryptWithPrivateKey(encrypted, pemPrivateKey);
|
|
102
|
+
expect(decrypted).toBe(testData);
|
|
103
|
+
});
|
|
104
|
+
it('should still work with base64-encoded PEM keys', () => {
|
|
105
|
+
// Base64 encode the PEM format
|
|
106
|
+
const pemPublicKey = `-----BEGIN PUBLIC KEY-----
|
|
107
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1M6wSqLb6VDlo1E1zQet
|
|
108
|
+
/F8ubAhvdcLLe8CKd66w154qZ4b0mYNSmw7DXR+wNz4k8VkP9Cxi/SxxHqj+PLYu
|
|
109
|
+
gHWftN/OFsSUASWRr0jiywQ5pbEngMU56Wy90iZmu9ngimdwinmuOjIuDFVyQNGb
|
|
110
|
+
8E9k1YcTUMqhbgV7OPjn2n6YuJje5A/bLXzrF9qwXxDlLz3Idc8oRDjL42/erifh
|
|
111
|
+
V7jPk6yFGD7TxHYAtaFP9Q6sQzNvPX3z4xJkTsRCDoFXGu5jCWxWKtXZTT7Jgpxo
|
|
112
|
+
5PWjR05aNSQu87UBDNM1a3cJygFGdi4k9lhVfK9NRLwX3IrGJx0EYpS70e6SYwmx
|
|
113
|
+
awIDAQAB
|
|
114
|
+
-----END PUBLIC KEY-----`;
|
|
115
|
+
const base64PublicKey = Buffer.from(pemPublicKey).toString('base64');
|
|
116
|
+
const testData = 'Test with base64-encoded PEM';
|
|
117
|
+
// Should work with base64-encoded PEM
|
|
118
|
+
expect(isValidPublicKey(base64PublicKey)).toBe(true);
|
|
119
|
+
const encrypted = encryptWithPublicKey(testData, base64PublicKey);
|
|
120
|
+
expect(encrypted).toBeDefined();
|
|
121
|
+
// Should be able to decrypt with raw private key
|
|
122
|
+
const decrypted = decryptWithPrivateKey(encrypted, rawPrivateKey);
|
|
123
|
+
expect(decrypted).toBe(testData);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
//# sourceMappingURL=new-format.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-format.test.mjs","sourceRoot":"","sources":["../../src/encryption/new-format.test.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-compatible RSA encryption using Web Crypto API
|
|
3
|
+
* This module provides RSA encryption functionality that works in browsers
|
|
4
|
+
*/
|
|
5
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
6
|
+
export type KeyFormat = 'pem' | 'base64';
|
|
7
|
+
export interface EncryptionOptions {
|
|
8
|
+
encoding?: BufferEncoding;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Encrypt data using an RSA public key in the browser
|
|
12
|
+
* @param data - Data to encrypt (string or object)
|
|
13
|
+
* @param publicKey - RSA public key in PEM or base64 format
|
|
14
|
+
* @param options - Encryption options
|
|
15
|
+
* @returns Promise resolving to encrypted data as base64 string
|
|
16
|
+
*/
|
|
17
|
+
export declare function encryptWithPublicKey(data: string | object, publicKey: string, _options?: EncryptionOptions): Promise<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Validate if a string is a valid RSA public key (browser version)
|
|
20
|
+
* @param key - Key string to validate
|
|
21
|
+
* @returns Promise resolving to true if valid public key
|
|
22
|
+
*/
|
|
23
|
+
export declare function isValidPublicKey(key: string): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Helper function to convert base64 string to PEM format
|
|
26
|
+
* @param base64Key - Base64 encoded key
|
|
27
|
+
* @param type - Type of key (PUBLIC or PRIVATE)
|
|
28
|
+
* @returns PEM formatted key
|
|
29
|
+
*/
|
|
30
|
+
export declare function base64ToPem(base64Key: string, type?: 'PUBLIC' | 'PRIVATE'): string;
|
|
31
|
+
/**
|
|
32
|
+
* Check if the browser supports Web Crypto API
|
|
33
|
+
* @returns true if Web Crypto API is available
|
|
34
|
+
*/
|
|
35
|
+
export declare function isWebCryptoSupported(): boolean;
|
|
36
|
+
//# sourceMappingURL=rsa-encryption.browser.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rsa-encryption.browser.d.mts","sourceRoot":"","sources":["../../src/encryption/rsa-encryption.browser.mts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEzC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AA0DD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,SAAS,EAAE,MAAM,EAEjB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAqCjB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAapE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,QAAQ,GAAG,SAAoB,GACpC,MAAM,CAqBR;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAM9C"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-compatible RSA encryption using Web Crypto API
|
|
3
|
+
* This module provides RSA encryption functionality that works in browsers
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Convert a PEM formatted public key to a format usable by Web Crypto API
|
|
7
|
+
* @param pem - PEM formatted public key string
|
|
8
|
+
* @returns ArrayBuffer containing the key data
|
|
9
|
+
*/
|
|
10
|
+
function pemToArrayBuffer(pem) {
|
|
11
|
+
// Remove PEM headers/footers and whitespace
|
|
12
|
+
const pemHeader = '-----BEGIN PUBLIC KEY-----';
|
|
13
|
+
const pemFooter = '-----END PUBLIC KEY-----';
|
|
14
|
+
let pemContents = pem;
|
|
15
|
+
pemContents = pemContents.replace(pemHeader, '');
|
|
16
|
+
pemContents = pemContents.replace(pemFooter, '');
|
|
17
|
+
pemContents = pemContents.replace(/\s/g, '');
|
|
18
|
+
// Convert base64 to binary
|
|
19
|
+
const binaryString = atob(pemContents);
|
|
20
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
21
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
22
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
23
|
+
}
|
|
24
|
+
return bytes.buffer;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Import a public key for use with Web Crypto API
|
|
28
|
+
* @param publicKey - RSA public key in PEM or base64 format
|
|
29
|
+
* @returns CryptoKey object for use with Web Crypto API
|
|
30
|
+
*/
|
|
31
|
+
async function importPublicKey(publicKey) {
|
|
32
|
+
let keyData;
|
|
33
|
+
// Check if it's PEM format or base64
|
|
34
|
+
if (publicKey.includes('-----BEGIN')) {
|
|
35
|
+
keyData = pemToArrayBuffer(publicKey);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// Assume it's base64 encoded PEM
|
|
39
|
+
const pemKey = atob(publicKey);
|
|
40
|
+
keyData = pemToArrayBuffer(pemKey);
|
|
41
|
+
}
|
|
42
|
+
// Import the key using Web Crypto API
|
|
43
|
+
return await crypto.subtle.importKey('spki', // SubjectPublicKeyInfo format
|
|
44
|
+
keyData, {
|
|
45
|
+
name: 'RSA-OAEP',
|
|
46
|
+
hash: 'SHA-256',
|
|
47
|
+
}, false, // not extractable
|
|
48
|
+
['encrypt']);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Encrypt data using an RSA public key in the browser
|
|
52
|
+
* @param data - Data to encrypt (string or object)
|
|
53
|
+
* @param publicKey - RSA public key in PEM or base64 format
|
|
54
|
+
* @param options - Encryption options
|
|
55
|
+
* @returns Promise resolving to encrypted data as base64 string
|
|
56
|
+
*/
|
|
57
|
+
export async function encryptWithPublicKey(data, publicKey,
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
59
|
+
_options) {
|
|
60
|
+
// Note: options parameter is kept for API compatibility but not used in browser version
|
|
61
|
+
// Browser always returns base64 encoded encrypted data
|
|
62
|
+
// Convert data to string if it's an object
|
|
63
|
+
const dataString = typeof data === 'object' ? JSON.stringify(data) : data;
|
|
64
|
+
// Convert string to Uint8Array
|
|
65
|
+
const encoder = new TextEncoder();
|
|
66
|
+
const dataBuffer = encoder.encode(dataString);
|
|
67
|
+
try {
|
|
68
|
+
// Import the public key
|
|
69
|
+
const cryptoKey = await importPublicKey(publicKey);
|
|
70
|
+
// Encrypt the data
|
|
71
|
+
const encryptedBuffer = await crypto.subtle.encrypt({
|
|
72
|
+
name: 'RSA-OAEP',
|
|
73
|
+
}, cryptoKey, dataBuffer);
|
|
74
|
+
// Convert encrypted data to base64
|
|
75
|
+
const encryptedArray = new Uint8Array(encryptedBuffer);
|
|
76
|
+
let binaryString = '';
|
|
77
|
+
for (let i = 0; i < encryptedArray.length; i++) {
|
|
78
|
+
binaryString += String.fromCharCode(encryptedArray[i]);
|
|
79
|
+
}
|
|
80
|
+
return btoa(binaryString);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
throw new Error(`Failed to encrypt data: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Validate if a string is a valid RSA public key (browser version)
|
|
88
|
+
* @param key - Key string to validate
|
|
89
|
+
* @returns Promise resolving to true if valid public key
|
|
90
|
+
*/
|
|
91
|
+
export async function isValidPublicKey(key) {
|
|
92
|
+
try {
|
|
93
|
+
// Check if it contains private key markers
|
|
94
|
+
if (key.includes('PRIVATE KEY')) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
// Try to import the key
|
|
98
|
+
await importPublicKey(key);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Helper function to convert base64 string to PEM format
|
|
107
|
+
* @param base64Key - Base64 encoded key
|
|
108
|
+
* @param type - Type of key (PUBLIC or PRIVATE)
|
|
109
|
+
* @returns PEM formatted key
|
|
110
|
+
*/
|
|
111
|
+
export function base64ToPem(base64Key, type = 'PUBLIC') {
|
|
112
|
+
const pemHeader = `-----BEGIN ${type} KEY-----`;
|
|
113
|
+
const pemFooter = `-----END ${type} KEY-----`;
|
|
114
|
+
// Decode base64 to check if it's already PEM
|
|
115
|
+
try {
|
|
116
|
+
const decoded = atob(base64Key);
|
|
117
|
+
if (decoded.includes('-----BEGIN')) {
|
|
118
|
+
return decoded;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// If decoding fails, assume it's already PEM
|
|
123
|
+
if (base64Key.includes('-----BEGIN')) {
|
|
124
|
+
return base64Key;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Format as PEM with line breaks every 64 characters
|
|
128
|
+
const formatted = base64Key.match(/.{1,64}/g)?.join('\n') || base64Key;
|
|
129
|
+
return `${pemHeader}\n${formatted}\n${pemFooter}`;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if the browser supports Web Crypto API
|
|
133
|
+
* @returns true if Web Crypto API is available
|
|
134
|
+
*/
|
|
135
|
+
export function isWebCryptoSupported() {
|
|
136
|
+
return (typeof window !== 'undefined' &&
|
|
137
|
+
window.crypto !== undefined &&
|
|
138
|
+
window.crypto.subtle !== undefined);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=rsa-encryption.browser.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rsa-encryption.browser.mjs","sourceRoot":"","sources":["../../src/encryption/rsa-encryption.browser.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
+
import { KeyObject } from 'crypto';
|
|
4
|
+
export type KeySize = 2048 | 3072 | 4096;
|
|
5
|
+
export type KeyFormat = 'pem' | 'base64';
|
|
6
|
+
export interface RSAKeyPair {
|
|
7
|
+
publicKey: string;
|
|
8
|
+
privateKey: string;
|
|
9
|
+
}
|
|
10
|
+
export interface RSAKeyPairObjects {
|
|
11
|
+
publicKey: KeyObject;
|
|
12
|
+
privateKey: KeyObject;
|
|
13
|
+
}
|
|
14
|
+
export interface GenerateKeyPairOptions {
|
|
15
|
+
keySize?: KeySize;
|
|
16
|
+
format?: KeyFormat;
|
|
17
|
+
}
|
|
18
|
+
export interface EncryptionOptions {
|
|
19
|
+
encoding?: BufferEncoding;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generate an RSA key pair synchronously
|
|
23
|
+
* @param options - Options for key generation
|
|
24
|
+
* @returns RSA key pair in the specified format
|
|
25
|
+
*/
|
|
26
|
+
export declare function generateKeyPairSync(options?: GenerateKeyPairOptions): RSAKeyPair;
|
|
27
|
+
/**
|
|
28
|
+
* Generate an RSA key pair asynchronously
|
|
29
|
+
* @param options - Options for key generation
|
|
30
|
+
* @returns Promise resolving to RSA key pair in the specified format
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateKeyPair(options?: GenerateKeyPairOptions): Promise<RSAKeyPair>;
|
|
33
|
+
/**
|
|
34
|
+
* Encrypt data using an RSA public key
|
|
35
|
+
* Supports three key formats:
|
|
36
|
+
* 1. PEM format (with -----BEGIN PUBLIC KEY-----)
|
|
37
|
+
* 2. Base64 encoded PEM
|
|
38
|
+
* 3. Raw base64 key material (without PEM headers)
|
|
39
|
+
* @param data - Data to encrypt (string or object)
|
|
40
|
+
* @param publicKey - RSA public key in any supported format
|
|
41
|
+
* @param options - Encryption options
|
|
42
|
+
* @returns Encrypted data as base64 string
|
|
43
|
+
*/
|
|
44
|
+
export declare function encryptWithPublicKey(data: string | object, publicKey: string, options?: EncryptionOptions): string;
|
|
45
|
+
/**
|
|
46
|
+
* Decrypt data using an RSA private key
|
|
47
|
+
* Supports three key formats:
|
|
48
|
+
* 1. PEM format (with -----BEGIN PRIVATE KEY-----)
|
|
49
|
+
* 2. Base64 encoded PEM
|
|
50
|
+
* 3. Raw base64 key material (without PEM headers)
|
|
51
|
+
* @param encryptedData - Encrypted data as base64 string
|
|
52
|
+
* @param privateKey - RSA private key in any supported format
|
|
53
|
+
* @param options - Decryption options
|
|
54
|
+
* @returns Decrypted data as string or parsed object
|
|
55
|
+
*/
|
|
56
|
+
export declare function decryptWithPrivateKey(encryptedData: string, privateKey: string, options?: EncryptionOptions): string | object;
|
|
57
|
+
/**
|
|
58
|
+
* Export RSA keys to different formats
|
|
59
|
+
* @param keyPair - RSA key pair
|
|
60
|
+
* @param format - Target format
|
|
61
|
+
* @returns Key pair in the specified format
|
|
62
|
+
*/
|
|
63
|
+
export declare function exportKeys(keyPair: RSAKeyPair, format: KeyFormat): RSAKeyPair;
|
|
64
|
+
/**
|
|
65
|
+
* Import RSA keys from strings to KeyObject instances
|
|
66
|
+
* @param publicKey - Public key string (PEM, base64 encoded PEM, or raw base64)
|
|
67
|
+
* @param privateKey - Private key string (PEM, base64 encoded PEM, or raw base64)
|
|
68
|
+
* @returns KeyObject instances for the keys
|
|
69
|
+
*/
|
|
70
|
+
export declare function importKeys(publicKey: string, privateKey: string): RSAKeyPairObjects;
|
|
71
|
+
/**
|
|
72
|
+
* Validate if a string is a valid RSA public key
|
|
73
|
+
* @param key - Key string to validate
|
|
74
|
+
* @returns True if valid public key
|
|
75
|
+
*/
|
|
76
|
+
export declare function isValidPublicKey(key: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Validate if a string is a valid RSA private key
|
|
79
|
+
* @param key - Key string to validate
|
|
80
|
+
* @returns True if valid private key
|
|
81
|
+
*/
|
|
82
|
+
export declare function isValidPrivateKey(key: string): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Get the key size of an RSA key
|
|
85
|
+
* @param key - RSA key (public or private) in any supported format
|
|
86
|
+
* @returns Key size in bits
|
|
87
|
+
*/
|
|
88
|
+
export declare function getKeySize(key: string): number;
|
|
89
|
+
//# sourceMappingURL=rsa-encryption.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rsa-encryption.d.mts","sourceRoot":"","sources":["../../src/encryption/rsa-encryption.mts"],"names":[],"mappings":";;AAAA,OAAO,EAML,SAAS,EAGV,MAAM,QAAQ,CAAC;AAKhB,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACzC,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEzC,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,SAAS,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAoDD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,sBAA2B,GACnC,UAAU,CAuBZ;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,UAAU,CAAC,CAuBrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,iBAAsB,GAC9B,MAAM,CAqBR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,GAC9B,MAAM,GAAG,MAAM,CA8BjB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,GAAG,UAAU,CAiB7E;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,iBAAiB,CAQnB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAYrD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQtD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAsB9C"}
|