@avieldr/react-native-rsa 1.0.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/LICENSE +20 -0
- package/README.md +453 -0
- package/Rsa.podspec +23 -0
- package/android/build.gradle +69 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/rsa/RsaModule.kt +129 -0
- package/android/src/main/java/com/rsa/RsaPackage.kt +33 -0
- package/android/src/main/java/com/rsa/core/ASN1Utils.kt +201 -0
- package/android/src/main/java/com/rsa/core/Algorithms.kt +126 -0
- package/android/src/main/java/com/rsa/core/KeyUtils.kt +83 -0
- package/android/src/main/java/com/rsa/core/RSACipher.kt +71 -0
- package/android/src/main/java/com/rsa/core/RSAKeyGenerator.kt +125 -0
- package/android/src/main/java/com/rsa/core/RSASigner.kt +70 -0
- package/ios/ASN1Utils.swift +225 -0
- package/ios/Algorithms.swift +89 -0
- package/ios/KeyUtils.swift +125 -0
- package/ios/RSACipher.swift +77 -0
- package/ios/RSAKeyGenerator.swift +164 -0
- package/ios/RSASigner.swift +101 -0
- package/ios/Rsa.h +61 -0
- package/ios/Rsa.mm +216 -0
- package/lib/module/NativeRsa.js +16 -0
- package/lib/module/NativeRsa.js.map +1 -0
- package/lib/module/constants.js +24 -0
- package/lib/module/constants.js.map +1 -0
- package/lib/module/encoding.js +116 -0
- package/lib/module/encoding.js.map +1 -0
- package/lib/module/errors.js +135 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/index.js +232 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/keyInfo.js +286 -0
- package/lib/module/keyInfo.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeRsa.d.ts +32 -0
- package/lib/typescript/src/NativeRsa.d.ts.map +1 -0
- package/lib/typescript/src/constants.d.ts +21 -0
- package/lib/typescript/src/constants.d.ts.map +1 -0
- package/lib/typescript/src/encoding.d.ts +30 -0
- package/lib/typescript/src/encoding.d.ts.map +1 -0
- package/lib/typescript/src/errors.d.ts +47 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +122 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/keyInfo.d.ts +7 -0
- package/lib/typescript/src/keyInfo.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +63 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +133 -0
- package/src/NativeRsa.ts +59 -0
- package/src/constants.ts +25 -0
- package/src/encoding.ts +139 -0
- package/src/errors.ts +206 -0
- package/src/index.ts +305 -0
- package/src/keyInfo.ts +334 -0
- package/src/types.ts +85 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pure-JS UTF-8 ↔ Base64 encoding utilities.
|
|
5
|
+
*
|
|
6
|
+
* These work in all React Native JS engines (Hermes, JSC) without
|
|
7
|
+
* external dependencies. They handle full Unicode including surrogate pairs.
|
|
8
|
+
*
|
|
9
|
+
* Used by the public API to convert UTF-8 input strings to base64
|
|
10
|
+
* before sending them across the native bridge.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Encode a UTF-8 string to base64.
|
|
17
|
+
*
|
|
18
|
+
* Steps:
|
|
19
|
+
* 1. Convert the JS string (UTF-16) to UTF-8 byte values
|
|
20
|
+
* 2. Encode those bytes as base64
|
|
21
|
+
*
|
|
22
|
+
* Handles multi-byte characters and surrogate pairs correctly.
|
|
23
|
+
*/
|
|
24
|
+
export function utf8ToBase64(str) {
|
|
25
|
+
// Step 1: UTF-16 string → UTF-8 byte array
|
|
26
|
+
const bytes = [];
|
|
27
|
+
for (let i = 0; i < str.length; i++) {
|
|
28
|
+
let codePoint = str.codePointAt(i);
|
|
29
|
+
// Skip the low surrogate of a surrogate pair (codePointAt already decoded it)
|
|
30
|
+
if (codePoint > 0xffff) {
|
|
31
|
+
i++;
|
|
32
|
+
}
|
|
33
|
+
if (codePoint < 0x80) {
|
|
34
|
+
// 1-byte: ASCII (0xxxxxxx)
|
|
35
|
+
bytes.push(codePoint);
|
|
36
|
+
} else if (codePoint < 0x800) {
|
|
37
|
+
// 2-byte: (110xxxxx 10xxxxxx)
|
|
38
|
+
bytes.push(0xc0 | codePoint >> 6, 0x80 | codePoint & 0x3f);
|
|
39
|
+
} else if (codePoint < 0x10000) {
|
|
40
|
+
// 3-byte: (1110xxxx 10xxxxxx 10xxxxxx)
|
|
41
|
+
bytes.push(0xe0 | codePoint >> 12, 0x80 | codePoint >> 6 & 0x3f, 0x80 | codePoint & 0x3f);
|
|
42
|
+
} else {
|
|
43
|
+
// 4-byte: (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx) — for emoji, etc.
|
|
44
|
+
bytes.push(0xf0 | codePoint >> 18, 0x80 | codePoint >> 12 & 0x3f, 0x80 | codePoint >> 6 & 0x3f, 0x80 | codePoint & 0x3f);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Step 2: Byte array → Base64 string (3 bytes per group → 4 base64 chars)
|
|
49
|
+
let result = '';
|
|
50
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
51
|
+
const a = bytes[i];
|
|
52
|
+
const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
|
|
53
|
+
const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
|
|
54
|
+
result += BASE64_CHARS[a >> 2];
|
|
55
|
+
result += BASE64_CHARS[(a & 3) << 4 | b >> 4];
|
|
56
|
+
result += i + 1 < bytes.length ? BASE64_CHARS[(b & 0xf) << 2 | c >> 6] : '=';
|
|
57
|
+
result += i + 2 < bytes.length ? BASE64_CHARS[c & 0x3f] : '=';
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Decode a base64 string to a UTF-8 string.
|
|
64
|
+
*
|
|
65
|
+
* Steps:
|
|
66
|
+
* 1. Decode base64 → raw byte values
|
|
67
|
+
* 2. Interpret those bytes as UTF-8 and build a JS string
|
|
68
|
+
*
|
|
69
|
+
* Useful for reading decrypted plaintext that was originally UTF-8 text.
|
|
70
|
+
*/
|
|
71
|
+
export function base64ToUtf8(base64) {
|
|
72
|
+
// Step 1: Base64 string → byte array
|
|
73
|
+
const cleaned = base64.replace(/[^A-Za-z0-9+/=]/g, '');
|
|
74
|
+
const bytes = [];
|
|
75
|
+
for (let i = 0; i < cleaned.length; i += 4) {
|
|
76
|
+
const a = BASE64_CHARS.indexOf(cleaned[i]);
|
|
77
|
+
const b = BASE64_CHARS.indexOf(cleaned[i + 1]);
|
|
78
|
+
const c = cleaned[i + 2] === '=' ? 0 : BASE64_CHARS.indexOf(cleaned[i + 2]);
|
|
79
|
+
const d = cleaned[i + 3] === '=' ? 0 : BASE64_CHARS.indexOf(cleaned[i + 3]);
|
|
80
|
+
const bits = a << 18 | b << 12 | c << 6 | d;
|
|
81
|
+
bytes.push(bits >> 16 & 0xff);
|
|
82
|
+
if (cleaned[i + 2] !== '=') {
|
|
83
|
+
bytes.push(bits >> 8 & 0xff);
|
|
84
|
+
}
|
|
85
|
+
if (cleaned[i + 3] !== '=') {
|
|
86
|
+
bytes.push(bits & 0xff);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Step 2: UTF-8 byte array → JS string
|
|
91
|
+
let str = '';
|
|
92
|
+
let idx = 0;
|
|
93
|
+
while (idx < bytes.length) {
|
|
94
|
+
const byte = bytes[idx];
|
|
95
|
+
if (byte < 0x80) {
|
|
96
|
+
// 1-byte: ASCII
|
|
97
|
+
str += String.fromCodePoint(byte);
|
|
98
|
+
idx++;
|
|
99
|
+
} else if ((byte & 0xe0) === 0xc0) {
|
|
100
|
+
// 2-byte character
|
|
101
|
+
str += String.fromCodePoint((byte & 0x1f) << 6 | bytes[idx + 1] & 0x3f);
|
|
102
|
+
idx += 2;
|
|
103
|
+
} else if ((byte & 0xf0) === 0xe0) {
|
|
104
|
+
// 3-byte character
|
|
105
|
+
str += String.fromCodePoint((byte & 0x0f) << 12 | (bytes[idx + 1] & 0x3f) << 6 | bytes[idx + 2] & 0x3f);
|
|
106
|
+
idx += 3;
|
|
107
|
+
} else {
|
|
108
|
+
// 4-byte character (emoji, etc.)
|
|
109
|
+
const codePoint = (byte & 0x07) << 18 | (bytes[idx + 1] & 0x3f) << 12 | (bytes[idx + 2] & 0x3f) << 6 | bytes[idx + 3] & 0x3f;
|
|
110
|
+
str += String.fromCodePoint(codePoint);
|
|
111
|
+
idx += 4;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return str;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=encoding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["BASE64_CHARS","utf8ToBase64","str","bytes","i","length","codePoint","codePointAt","push","result","a","b","c","base64ToUtf8","base64","cleaned","replace","indexOf","d","bits","idx","byte","String","fromCodePoint"],"sourceRoot":"../../src","sources":["encoding.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { VALID_KEY_SIZES } from "./constants.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Error codes thrown by @avieldr/react-native-rsa.
|
|
7
|
+
*
|
|
8
|
+
* Validation errors (thrown before native call):
|
|
9
|
+
* - INVALID_INPUT: Required parameter is missing or empty
|
|
10
|
+
* - INVALID_KEY: Key format is wrong or key type mismatch
|
|
11
|
+
* - INVALID_KEY_SIZE: Unsupported key size
|
|
12
|
+
* - INVALID_PADDING: Unknown padding mode
|
|
13
|
+
* - INVALID_HASH: Unknown hash algorithm
|
|
14
|
+
* - INVALID_FORMAT: Unknown key format
|
|
15
|
+
* - INVALID_ENCODING: Unknown encoding type
|
|
16
|
+
*
|
|
17
|
+
* Native operation errors (thrown by platform crypto):
|
|
18
|
+
* - KEY_GENERATION_FAILED: Native key generation failed
|
|
19
|
+
* - KEY_EXTRACTION_FAILED: Failed to extract public key from private
|
|
20
|
+
* - KEY_CONVERSION_FAILED: Failed to convert key format
|
|
21
|
+
* - ENCRYPTION_FAILED: Native encryption operation failed
|
|
22
|
+
* - DECRYPTION_FAILED: Native decryption operation failed
|
|
23
|
+
* - SIGNING_FAILED: Native signing operation failed
|
|
24
|
+
* - VERIFICATION_FAILED: Native signature verification failed
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Error thrown by @avieldr/react-native-rsa for invalid inputs or native failures.
|
|
29
|
+
* Extends Error with a `code` property for programmatic handling.
|
|
30
|
+
*/
|
|
31
|
+
export class RsaError extends Error {
|
|
32
|
+
/** The original error from the native layer, if any */
|
|
33
|
+
|
|
34
|
+
constructor(code, message, cause) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = 'RsaError';
|
|
37
|
+
this.code = code;
|
|
38
|
+
this.cause = cause;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Map of native error codes to RsaErrorCode.
|
|
44
|
+
* Native modules reject with codes like "RSAEncryptError" — we normalize them.
|
|
45
|
+
*/
|
|
46
|
+
const NATIVE_ERROR_CODE_MAP = {
|
|
47
|
+
RSAKeyGenerationError: 'KEY_GENERATION_FAILED',
|
|
48
|
+
RSAKeyExtractionError: 'KEY_EXTRACTION_FAILED',
|
|
49
|
+
RSAConvertKeyError: 'KEY_CONVERSION_FAILED',
|
|
50
|
+
RSAEncryptError: 'ENCRYPTION_FAILED',
|
|
51
|
+
RSADecryptError: 'DECRYPTION_FAILED',
|
|
52
|
+
RSASignError: 'SIGNING_FAILED',
|
|
53
|
+
RSAVerifyError: 'VERIFICATION_FAILED'
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Wrap a native error into an RsaError with a normalized code.
|
|
58
|
+
* If the error is already an RsaError, returns it unchanged.
|
|
59
|
+
*/
|
|
60
|
+
export function wrapNativeError(error, fallbackCode) {
|
|
61
|
+
if (error instanceof RsaError) {
|
|
62
|
+
return error;
|
|
63
|
+
}
|
|
64
|
+
if (error instanceof Error) {
|
|
65
|
+
// React Native errors from native modules have a `code` property
|
|
66
|
+
const nativeCode = error.code;
|
|
67
|
+
const code = nativeCode && NATIVE_ERROR_CODE_MAP[nativeCode] || fallbackCode;
|
|
68
|
+
return new RsaError(code, error.message, error);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Unknown error type
|
|
72
|
+
return new RsaError(fallbackCode, String(error));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// --- Validation helpers ---
|
|
76
|
+
|
|
77
|
+
export function requireString(value, name) {
|
|
78
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
79
|
+
throw new RsaError('INVALID_INPUT', `'${name}' must be a non-empty string`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export function requirePrivateKey(pem) {
|
|
83
|
+
requireString(pem, 'privateKey');
|
|
84
|
+
if (pem.includes('BEGIN PUBLIC KEY')) {
|
|
85
|
+
throw new RsaError('INVALID_KEY', 'Expected a private key (BEGIN RSA PRIVATE KEY or BEGIN PRIVATE KEY), but received a public key');
|
|
86
|
+
}
|
|
87
|
+
if (!pem.includes('BEGIN RSA PRIVATE KEY') && !pem.includes('BEGIN PRIVATE KEY')) {
|
|
88
|
+
throw new RsaError('INVALID_KEY', 'Expected a private key (BEGIN RSA PRIVATE KEY or BEGIN PRIVATE KEY)');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export function requirePublicKey(pem) {
|
|
92
|
+
requireString(pem, 'publicKey');
|
|
93
|
+
if (pem.includes('BEGIN RSA PRIVATE KEY') || pem.includes('BEGIN PRIVATE KEY')) {
|
|
94
|
+
throw new RsaError('INVALID_KEY', 'Expected a public key (BEGIN PUBLIC KEY), but received a private key');
|
|
95
|
+
}
|
|
96
|
+
if (!pem.includes('BEGIN PUBLIC KEY')) {
|
|
97
|
+
throw new RsaError('INVALID_KEY', 'Expected a public key (BEGIN PUBLIC KEY)');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export function validateKeySize(keySize) {
|
|
101
|
+
if (!VALID_KEY_SIZES.includes(keySize)) {
|
|
102
|
+
throw new RsaError('INVALID_KEY_SIZE', `Invalid key size ${keySize}. Supported sizes: ${VALID_KEY_SIZES.join(', ')}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const VALID_ENCRYPTION_PADDINGS = ['oaep', 'pkcs1'];
|
|
106
|
+
export function validateEncryptionPadding(padding) {
|
|
107
|
+
if (!VALID_ENCRYPTION_PADDINGS.includes(padding)) {
|
|
108
|
+
throw new RsaError('INVALID_PADDING', `Invalid encryption padding '${padding}'. Must be 'oaep' or 'pkcs1'`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const VALID_SIGNATURE_PADDINGS = ['pss', 'pkcs1'];
|
|
112
|
+
export function validateSignaturePadding(padding) {
|
|
113
|
+
if (!VALID_SIGNATURE_PADDINGS.includes(padding)) {
|
|
114
|
+
throw new RsaError('INVALID_PADDING', `Invalid signature padding '${padding}'. Must be 'pss' or 'pkcs1'`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const VALID_HASHES = ['sha1', 'sha256', 'sha384', 'sha512'];
|
|
118
|
+
export function validateHash(hash) {
|
|
119
|
+
if (!VALID_HASHES.includes(hash)) {
|
|
120
|
+
throw new RsaError('INVALID_HASH', `Invalid hash '${hash}'. Must be 'sha1', 'sha256', 'sha384', or 'sha512'`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const VALID_KEY_FORMATS = ['pkcs1', 'pkcs8'];
|
|
124
|
+
export function validateKeyFormat(format) {
|
|
125
|
+
if (!VALID_KEY_FORMATS.includes(format)) {
|
|
126
|
+
throw new RsaError('INVALID_FORMAT', `Invalid key format '${format}'. Must be 'pkcs1' or 'pkcs8'`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const VALID_ENCODINGS = ['utf8', 'base64'];
|
|
130
|
+
export function validateEncoding(encoding) {
|
|
131
|
+
if (!VALID_ENCODINGS.includes(encoding)) {
|
|
132
|
+
throw new RsaError('INVALID_ENCODING', `Invalid encoding '${encoding}'. Must be 'utf8' or 'base64'`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["VALID_KEY_SIZES","RsaError","Error","constructor","code","message","cause","name","NATIVE_ERROR_CODE_MAP","RSAKeyGenerationError","RSAKeyExtractionError","RSAConvertKeyError","RSAEncryptError","RSADecryptError","RSASignError","RSAVerifyError","wrapNativeError","error","fallbackCode","nativeCode","String","requireString","value","length","requirePrivateKey","pem","includes","requirePublicKey","validateKeySize","keySize","join","VALID_ENCRYPTION_PADDINGS","validateEncryptionPadding","padding","VALID_SIGNATURE_PADDINGS","validateSignaturePadding","VALID_HASHES","validateHash","hash","VALID_KEY_FORMATS","validateKeyFormat","format","VALID_ENCODINGS","validateEncoding","encoding"],"sourceRoot":"../../src","sources":["errors.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import NativeRsa from "./NativeRsa.js";
|
|
4
|
+
import { getKeyInfo } from "./keyInfo.js";
|
|
5
|
+
import { utf8ToBase64 } from "./encoding.js";
|
|
6
|
+
import { DEFAULTS } from "./constants.js";
|
|
7
|
+
import { requireString, requirePrivateKey, requirePublicKey, validateKeySize, validateEncryptionPadding, validateSignaturePadding, validateHash, validateKeyFormat, validateEncoding, wrapNativeError } from "./errors.js";
|
|
8
|
+
|
|
9
|
+
// Re-export all public types
|
|
10
|
+
|
|
11
|
+
// Re-export error class, error code type, and utilities that consumers may need
|
|
12
|
+
export { RsaError } from "./errors.js";
|
|
13
|
+
export { getKeyInfo } from "./keyInfo.js";
|
|
14
|
+
export { utf8ToBase64, base64ToUtf8 } from "./encoding.js";
|
|
15
|
+
|
|
16
|
+
// --- Key Generation ---
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generate an RSA key pair (public + private) using native platform crypto.
|
|
20
|
+
*
|
|
21
|
+
* @param keySize RSA key size in bits. Default: 2048. Supported: 1024, 2048, 4096.
|
|
22
|
+
* @param options Optional configuration (format: 'pkcs1' | 'pkcs8')
|
|
23
|
+
* @returns Object with publicKey and privateKey in PEM format
|
|
24
|
+
* @throws {RsaError} INVALID_KEY_SIZE if keySize is not 1024, 2048, or 4096
|
|
25
|
+
* @throws {RsaError} INVALID_FORMAT if options.format is not 'pkcs1' or 'pkcs8'
|
|
26
|
+
* @throws {RsaError} KEY_GENERATION_FAILED if native key generation fails
|
|
27
|
+
*/
|
|
28
|
+
async function generateKeyPair(keySize = 2048, options) {
|
|
29
|
+
validateKeySize(keySize);
|
|
30
|
+
const format = options?.format ?? DEFAULTS.KEY_FORMAT;
|
|
31
|
+
validateKeyFormat(format);
|
|
32
|
+
try {
|
|
33
|
+
return await NativeRsa.generateKeyPair(keySize, format);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
throw wrapNativeError(error, 'KEY_GENERATION_FAILED');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Extract the public key from an RSA private key PEM string.
|
|
41
|
+
*
|
|
42
|
+
* @param privateKeyPEM RSA private key in PEM format (PKCS#1 or PKCS#8)
|
|
43
|
+
* @returns Public key in PEM format (SPKI/X.509)
|
|
44
|
+
* @throws {RsaError} INVALID_INPUT if privateKeyPEM is empty
|
|
45
|
+
* @throws {RsaError} INVALID_KEY if privateKeyPEM is not a valid private key
|
|
46
|
+
* @throws {RsaError} KEY_EXTRACTION_FAILED if native operation fails
|
|
47
|
+
*/
|
|
48
|
+
async function getPublicKeyFromPrivate(privateKeyPEM) {
|
|
49
|
+
requirePrivateKey(privateKeyPEM);
|
|
50
|
+
try {
|
|
51
|
+
return await NativeRsa.getPublicKeyFromPrivate(privateKeyPEM);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
throw wrapNativeError(error, 'KEY_EXTRACTION_FAILED');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// --- Encrypt / Decrypt ---
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Encrypt plaintext with an RSA public key.
|
|
61
|
+
*
|
|
62
|
+
* The input string is UTF-8 encoded to base64 by default before sending to native.
|
|
63
|
+
* Set `options.encoding = 'base64'` if the input is already base64-encoded binary.
|
|
64
|
+
*
|
|
65
|
+
* @param data The plaintext to encrypt (UTF-8 string or base64, depending on encoding option)
|
|
66
|
+
* @param publicKeyPEM The public key in SPKI PEM format
|
|
67
|
+
* @param options Padding, hash, and encoding options (defaults: oaep, sha256, utf8)
|
|
68
|
+
* @returns Base64-encoded ciphertext
|
|
69
|
+
* @throws {RsaError} INVALID_INPUT if data or publicKeyPEM is empty
|
|
70
|
+
* @throws {RsaError} INVALID_KEY if publicKeyPEM is not a valid public key
|
|
71
|
+
* @throws {RsaError} INVALID_PADDING if options.padding is invalid
|
|
72
|
+
* @throws {RsaError} INVALID_HASH if options.hash is invalid
|
|
73
|
+
* @throws {RsaError} INVALID_ENCODING if options.encoding is invalid
|
|
74
|
+
* @throws {RsaError} ENCRYPTION_FAILED if native encryption fails
|
|
75
|
+
*/
|
|
76
|
+
async function encrypt(data, publicKeyPEM, options) {
|
|
77
|
+
requireString(data, 'data');
|
|
78
|
+
requirePublicKey(publicKeyPEM);
|
|
79
|
+
const padding = options?.padding ?? DEFAULTS.ENCRYPTION_PADDING;
|
|
80
|
+
const hash = options?.hash ?? DEFAULTS.HASH;
|
|
81
|
+
const encoding = options?.encoding ?? DEFAULTS.ENCODING;
|
|
82
|
+
validateEncryptionPadding(padding);
|
|
83
|
+
validateHash(hash);
|
|
84
|
+
validateEncoding(encoding);
|
|
85
|
+
|
|
86
|
+
// Convert UTF-8 text to base64 for the native bridge; pass through if already base64
|
|
87
|
+
const dataBase64 = encoding === 'utf8' ? utf8ToBase64(data) : data;
|
|
88
|
+
try {
|
|
89
|
+
return await NativeRsa.encrypt(dataBase64, publicKeyPEM, padding, hash);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw wrapNativeError(error, 'ENCRYPTION_FAILED');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Decrypt ciphertext with an RSA private key.
|
|
97
|
+
*
|
|
98
|
+
* Always returns base64-encoded plaintext. If the original data was UTF-8 text,
|
|
99
|
+
* use `base64ToUtf8()` to decode the result.
|
|
100
|
+
*
|
|
101
|
+
* @param encrypted Base64-encoded ciphertext (from encrypt())
|
|
102
|
+
* @param privateKeyPEM The private key in PEM format (PKCS#1 or PKCS#8)
|
|
103
|
+
* @param options Padding and hash options — must match what was used for encryption
|
|
104
|
+
* @returns Base64-encoded decrypted plaintext
|
|
105
|
+
* @throws {RsaError} INVALID_INPUT if encrypted or privateKeyPEM is empty
|
|
106
|
+
* @throws {RsaError} INVALID_KEY if privateKeyPEM is not a valid private key
|
|
107
|
+
* @throws {RsaError} INVALID_PADDING if options.padding is invalid
|
|
108
|
+
* @throws {RsaError} INVALID_HASH if options.hash is invalid
|
|
109
|
+
* @throws {RsaError} DECRYPTION_FAILED if native decryption fails
|
|
110
|
+
*/
|
|
111
|
+
async function decrypt(encrypted, privateKeyPEM, options) {
|
|
112
|
+
requireString(encrypted, 'encrypted');
|
|
113
|
+
requirePrivateKey(privateKeyPEM);
|
|
114
|
+
const padding = options?.padding ?? DEFAULTS.ENCRYPTION_PADDING;
|
|
115
|
+
const hash = options?.hash ?? DEFAULTS.HASH;
|
|
116
|
+
validateEncryptionPadding(padding);
|
|
117
|
+
validateHash(hash);
|
|
118
|
+
try {
|
|
119
|
+
return await NativeRsa.decrypt(encrypted, privateKeyPEM, padding, hash);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
throw wrapNativeError(error, 'DECRYPTION_FAILED');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// --- Sign / Verify ---
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Sign data with an RSA private key.
|
|
129
|
+
*
|
|
130
|
+
* The input string is UTF-8 encoded to base64 by default before sending to native.
|
|
131
|
+
* Set `options.encoding = 'base64'` if the input is already base64-encoded binary.
|
|
132
|
+
*
|
|
133
|
+
* @param data The data to sign (UTF-8 string or base64, depending on encoding option)
|
|
134
|
+
* @param privateKeyPEM The private key in PEM format (PKCS#1 or PKCS#8)
|
|
135
|
+
* @param options Padding, hash, and encoding options (defaults: pss, sha256, utf8)
|
|
136
|
+
* @returns Base64-encoded signature
|
|
137
|
+
* @throws {RsaError} INVALID_INPUT if data or privateKeyPEM is empty
|
|
138
|
+
* @throws {RsaError} INVALID_KEY if privateKeyPEM is not a valid private key
|
|
139
|
+
* @throws {RsaError} INVALID_PADDING if options.padding is invalid
|
|
140
|
+
* @throws {RsaError} INVALID_HASH if options.hash is invalid
|
|
141
|
+
* @throws {RsaError} INVALID_ENCODING if options.encoding is invalid
|
|
142
|
+
* @throws {RsaError} SIGNING_FAILED if native signing fails
|
|
143
|
+
*/
|
|
144
|
+
async function sign(data, privateKeyPEM, options) {
|
|
145
|
+
requireString(data, 'data');
|
|
146
|
+
requirePrivateKey(privateKeyPEM);
|
|
147
|
+
const padding = options?.padding ?? DEFAULTS.SIGNATURE_PADDING;
|
|
148
|
+
const hash = options?.hash ?? DEFAULTS.HASH;
|
|
149
|
+
const encoding = options?.encoding ?? DEFAULTS.ENCODING;
|
|
150
|
+
validateSignaturePadding(padding);
|
|
151
|
+
validateHash(hash);
|
|
152
|
+
validateEncoding(encoding);
|
|
153
|
+
const dataBase64 = encoding === 'utf8' ? utf8ToBase64(data) : data;
|
|
154
|
+
try {
|
|
155
|
+
return await NativeRsa.sign(dataBase64, privateKeyPEM, padding, hash);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
throw wrapNativeError(error, 'SIGNING_FAILED');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Verify a signature against data using an RSA public key.
|
|
163
|
+
*
|
|
164
|
+
* The input string encoding must match what was used during signing.
|
|
165
|
+
*
|
|
166
|
+
* @param data The original data that was signed
|
|
167
|
+
* @param signature Base64-encoded signature (from sign())
|
|
168
|
+
* @param publicKeyPEM The public key in SPKI PEM format
|
|
169
|
+
* @param options Padding, hash, and encoding options — must match signing options
|
|
170
|
+
* @returns true if the signature is valid, false otherwise
|
|
171
|
+
* @throws {RsaError} INVALID_INPUT if data, signature, or publicKeyPEM is empty
|
|
172
|
+
* @throws {RsaError} INVALID_KEY if publicKeyPEM is not a valid public key
|
|
173
|
+
* @throws {RsaError} INVALID_PADDING if options.padding is invalid
|
|
174
|
+
* @throws {RsaError} INVALID_HASH if options.hash is invalid
|
|
175
|
+
* @throws {RsaError} INVALID_ENCODING if options.encoding is invalid
|
|
176
|
+
* @throws {RsaError} VERIFICATION_FAILED if native verification fails
|
|
177
|
+
*/
|
|
178
|
+
async function verify(data, signature, publicKeyPEM, options) {
|
|
179
|
+
requireString(data, 'data');
|
|
180
|
+
requireString(signature, 'signature');
|
|
181
|
+
requirePublicKey(publicKeyPEM);
|
|
182
|
+
const padding = options?.padding ?? DEFAULTS.SIGNATURE_PADDING;
|
|
183
|
+
const hash = options?.hash ?? DEFAULTS.HASH;
|
|
184
|
+
const encoding = options?.encoding ?? DEFAULTS.ENCODING;
|
|
185
|
+
validateSignaturePadding(padding);
|
|
186
|
+
validateHash(hash);
|
|
187
|
+
validateEncoding(encoding);
|
|
188
|
+
const dataBase64 = encoding === 'utf8' ? utf8ToBase64(data) : data;
|
|
189
|
+
try {
|
|
190
|
+
return await NativeRsa.verify(dataBase64, signature, publicKeyPEM, padding, hash);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
throw wrapNativeError(error, 'VERIFICATION_FAILED');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// --- Key Format Conversion ---
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Convert a private key PEM between PKCS#1 and PKCS#8 formats.
|
|
200
|
+
*
|
|
201
|
+
* @param pem The private key in PEM format
|
|
202
|
+
* @param targetFormat 'pkcs1' or 'pkcs8'
|
|
203
|
+
* @returns The private key re-encoded in the target format
|
|
204
|
+
* @throws {RsaError} INVALID_INPUT if pem is empty
|
|
205
|
+
* @throws {RsaError} INVALID_KEY if pem is not a valid private key
|
|
206
|
+
* @throws {RsaError} INVALID_FORMAT if targetFormat is invalid
|
|
207
|
+
* @throws {RsaError} KEY_CONVERSION_FAILED if native conversion fails
|
|
208
|
+
*/
|
|
209
|
+
async function convertPrivateKey(pem, targetFormat) {
|
|
210
|
+
requirePrivateKey(pem);
|
|
211
|
+
validateKeyFormat(targetFormat);
|
|
212
|
+
try {
|
|
213
|
+
return await NativeRsa.convertPrivateKey(pem, targetFormat);
|
|
214
|
+
} catch (error) {
|
|
215
|
+
throw wrapNativeError(error, 'KEY_CONVERSION_FAILED');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// --- Default Export ---
|
|
220
|
+
|
|
221
|
+
const RSA = {
|
|
222
|
+
generateKeyPair,
|
|
223
|
+
getPublicKeyFromPrivate,
|
|
224
|
+
getKeyInfo,
|
|
225
|
+
encrypt,
|
|
226
|
+
decrypt,
|
|
227
|
+
sign,
|
|
228
|
+
verify,
|
|
229
|
+
convertPrivateKey
|
|
230
|
+
};
|
|
231
|
+
export default RSA;
|
|
232
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeRsa","getKeyInfo","utf8ToBase64","DEFAULTS","requireString","requirePrivateKey","requirePublicKey","validateKeySize","validateEncryptionPadding","validateSignaturePadding","validateHash","validateKeyFormat","validateEncoding","wrapNativeError","RsaError","base64ToUtf8","generateKeyPair","keySize","options","format","KEY_FORMAT","error","getPublicKeyFromPrivate","privateKeyPEM","encrypt","data","publicKeyPEM","padding","ENCRYPTION_PADDING","hash","HASH","encoding","ENCODING","dataBase64","decrypt","encrypted","sign","SIGNATURE_PADDING","verify","signature","convertPrivateKey","pem","targetFormat","RSA"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,OAAOA,SAAS,MAAM,gBAAa;AACnC,SAASC,UAAU,QAAQ,cAAW;AACtC,SAASC,YAAY,QAAQ,eAAY;AACzC,SAASC,QAAQ,QAAQ,gBAAa;AACtC,SACEC,aAAa,EACbC,iBAAiB,EACjBC,gBAAgB,EAChBC,eAAe,EACfC,yBAAyB,EACzBC,wBAAwB,EACxBC,YAAY,EACZC,iBAAiB,EACjBC,gBAAgB,EAChBC,eAAe,QACV,aAAU;;AAWjB;;AAgBA;AACA,SAASC,QAAQ,QAA2B,aAAU;AACtD,SAASb,UAAU,QAAQ,cAAW;AACtC,SAASC,YAAY,EAAEa,YAAY,QAAQ,eAAY;;AAEvD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeC,eAAeA,CAC5BC,OAAe,GAAG,IAAI,EACtBC,OAAgC,EACX;EACrBX,eAAe,CAACU,OAAO,CAAC;EACxB,MAAME,MAAM,GAAGD,OAAO,EAAEC,MAAM,IAAIhB,QAAQ,CAACiB,UAAU;EACrDT,iBAAiB,CAACQ,MAAM,CAAC;EAEzB,IAAI;IACF,OAAO,MAAMnB,SAAS,CAACgB,eAAe,CAACC,OAAO,EAAEE,MAAM,CAAC;EACzD,CAAC,CAAC,OAAOE,KAAK,EAAE;IACd,MAAMR,eAAe,CAACQ,KAAK,EAAE,uBAAuB,CAAC;EACvD;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeC,uBAAuBA,CACpCC,aAAqB,EACJ;EACjBlB,iBAAiB,CAACkB,aAAa,CAAC;EAEhC,IAAI;IACF,OAAO,MAAMvB,SAAS,CAACsB,uBAAuB,CAACC,aAAa,CAAC;EAC/D,CAAC,CAAC,OAAOF,KAAK,EAAE;IACd,MAAMR,eAAe,CAACQ,KAAK,EAAE,uBAAuB,CAAC;EACvD;AACF;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeG,OAAOA,CACpBC,IAAY,EACZC,YAAoB,EACpBR,OAAwB,EACP;EACjBd,aAAa,CAACqB,IAAI,EAAE,MAAM,CAAC;EAC3BnB,gBAAgB,CAACoB,YAAY,CAAC;EAE9B,MAAMC,OAAO,GAAGT,OAAO,EAAES,OAAO,IAAIxB,QAAQ,CAACyB,kBAAkB;EAC/D,MAAMC,IAAI,GAAGX,OAAO,EAAEW,IAAI,IAAI1B,QAAQ,CAAC2B,IAAI;EAC3C,MAAMC,QAAQ,GAAGb,OAAO,EAAEa,QAAQ,IAAI5B,QAAQ,CAAC6B,QAAQ;EAEvDxB,yBAAyB,CAACmB,OAAO,CAAC;EAClCjB,YAAY,CAACmB,IAAI,CAAC;EAClBjB,gBAAgB,CAACmB,QAAQ,CAAC;;EAE1B;EACA,MAAME,UAAU,GAAGF,QAAQ,KAAK,MAAM,GAAG7B,YAAY,CAACuB,IAAI,CAAC,GAAGA,IAAI;EAElE,IAAI;IACF,OAAO,MAAMzB,SAAS,CAACwB,OAAO,CAACS,UAAU,EAAEP,YAAY,EAAEC,OAAO,EAAEE,IAAI,CAAC;EACzE,CAAC,CAAC,OAAOR,KAAK,EAAE;IACd,MAAMR,eAAe,CAACQ,KAAK,EAAE,mBAAmB,CAAC;EACnD;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAea,OAAOA,CACpBC,SAAiB,EACjBZ,aAAqB,EACrBL,OAAwB,EACP;EACjBd,aAAa,CAAC+B,SAAS,EAAE,WAAW,CAAC;EACrC9B,iBAAiB,CAACkB,aAAa,CAAC;EAEhC,MAAMI,OAAO,GAAGT,OAAO,EAAES,OAAO,IAAIxB,QAAQ,CAACyB,kBAAkB;EAC/D,MAAMC,IAAI,GAAGX,OAAO,EAAEW,IAAI,IAAI1B,QAAQ,CAAC2B,IAAI;EAE3CtB,yBAAyB,CAACmB,OAAO,CAAC;EAClCjB,YAAY,CAACmB,IAAI,CAAC;EAElB,IAAI;IACF,OAAO,MAAM7B,SAAS,CAACkC,OAAO,CAACC,SAAS,EAAEZ,aAAa,EAAEI,OAAO,EAAEE,IAAI,CAAC;EACzE,CAAC,CAAC,OAAOR,KAAK,EAAE;IACd,MAAMR,eAAe,CAACQ,KAAK,EAAE,mBAAmB,CAAC;EACnD;AACF;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAee,IAAIA,CACjBX,IAAY,EACZF,aAAqB,EACrBL,OAAqB,EACJ;EACjBd,aAAa,CAACqB,IAAI,EAAE,MAAM,CAAC;EAC3BpB,iBAAiB,CAACkB,aAAa,CAAC;EAEhC,MAAMI,OAAO,GAAGT,OAAO,EAAES,OAAO,IAAIxB,QAAQ,CAACkC,iBAAiB;EAC9D,MAAMR,IAAI,GAAGX,OAAO,EAAEW,IAAI,IAAI1B,QAAQ,CAAC2B,IAAI;EAC3C,MAAMC,QAAQ,GAAGb,OAAO,EAAEa,QAAQ,IAAI5B,QAAQ,CAAC6B,QAAQ;EAEvDvB,wBAAwB,CAACkB,OAAO,CAAC;EACjCjB,YAAY,CAACmB,IAAI,CAAC;EAClBjB,gBAAgB,CAACmB,QAAQ,CAAC;EAE1B,MAAME,UAAU,GAAGF,QAAQ,KAAK,MAAM,GAAG7B,YAAY,CAACuB,IAAI,CAAC,GAAGA,IAAI;EAElE,IAAI;IACF,OAAO,MAAMzB,SAAS,CAACoC,IAAI,CAACH,UAAU,EAAEV,aAAa,EAAEI,OAAO,EAAEE,IAAI,CAAC;EACvE,CAAC,CAAC,OAAOR,KAAK,EAAE;IACd,MAAMR,eAAe,CAACQ,KAAK,EAAE,gBAAgB,CAAC;EAChD;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeiB,MAAMA,CACnBb,IAAY,EACZc,SAAiB,EACjBb,YAAoB,EACpBR,OAAuB,EACL;EAClBd,aAAa,CAACqB,IAAI,EAAE,MAAM,CAAC;EAC3BrB,aAAa,CAACmC,SAAS,EAAE,WAAW,CAAC;EACrCjC,gBAAgB,CAACoB,YAAY,CAAC;EAE9B,MAAMC,OAAO,GAAGT,OAAO,EAAES,OAAO,IAAIxB,QAAQ,CAACkC,iBAAiB;EAC9D,MAAMR,IAAI,GAAGX,OAAO,EAAEW,IAAI,IAAI1B,QAAQ,CAAC2B,IAAI;EAC3C,MAAMC,QAAQ,GAAGb,OAAO,EAAEa,QAAQ,IAAI5B,QAAQ,CAAC6B,QAAQ;EAEvDvB,wBAAwB,CAACkB,OAAO,CAAC;EACjCjB,YAAY,CAACmB,IAAI,CAAC;EAClBjB,gBAAgB,CAACmB,QAAQ,CAAC;EAE1B,MAAME,UAAU,GAAGF,QAAQ,KAAK,MAAM,GAAG7B,YAAY,CAACuB,IAAI,CAAC,GAAGA,IAAI;EAElE,IAAI;IACF,OAAO,MAAMzB,SAAS,CAACsC,MAAM,CAACL,UAAU,EAAEM,SAAS,EAAEb,YAAY,EAAEC,OAAO,EAAEE,IAAI,CAAC;EACnF,CAAC,CAAC,OAAOR,KAAK,EAAE;IACd,MAAMR,eAAe,CAACQ,KAAK,EAAE,qBAAqB,CAAC;EACrD;AACF;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAemB,iBAAiBA,CAC9BC,GAAW,EACXC,YAAuB,EACN;EACjBrC,iBAAiB,CAACoC,GAAG,CAAC;EACtB9B,iBAAiB,CAAC+B,YAAY,CAAC;EAE/B,IAAI;IACF,OAAO,MAAM1C,SAAS,CAACwC,iBAAiB,CAACC,GAAG,EAAEC,YAAY,CAAC;EAC7D,CAAC,CAAC,OAAOrB,KAAK,EAAE;IACd,MAAMR,eAAe,CAACQ,KAAK,EAAE,uBAAuB,CAAC;EACvD;AACF;;AAEA;;AAEA,MAAMsB,GAAG,GAAG;EACV3B,eAAe;EACfM,uBAAuB;EACvBrB,UAAU;EACVuB,OAAO;EACPU,OAAO;EACPE,IAAI;EACJE,MAAM;EACNE;AACF,CAAC;AACD,eAAeG,GAAG","ignoreList":[]}
|