@ricsam/quickjs-crypto 0.0.1 → 0.2.14
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 +73 -43
- package/dist/cjs/crypto-key.cjs +70 -0
- package/dist/cjs/crypto-key.cjs.map +10 -0
- package/dist/cjs/index.cjs +41 -0
- package/dist/cjs/index.cjs.map +10 -0
- package/dist/cjs/package.json +5 -0
- package/dist/cjs/random.cjs +89 -0
- package/dist/cjs/random.cjs.map +10 -0
- package/dist/cjs/setup.cjs +88 -0
- package/dist/cjs/setup.cjs.map +10 -0
- package/dist/cjs/subtle-crypto.cjs +307 -0
- package/dist/cjs/subtle-crypto.cjs.map +10 -0
- package/dist/cjs/types.cjs +26 -0
- package/dist/cjs/types.cjs.map +9 -0
- package/dist/mjs/crypto-key.mjs +39 -0
- package/dist/mjs/crypto-key.mjs.map +10 -0
- package/dist/mjs/index.mjs +10 -0
- package/dist/mjs/index.mjs.map +10 -0
- package/dist/mjs/package.json +5 -0
- package/dist/mjs/random.mjs +58 -0
- package/dist/mjs/random.mjs.map +10 -0
- package/dist/mjs/setup.mjs +60 -0
- package/dist/mjs/setup.mjs.map +10 -0
- package/dist/mjs/subtle-crypto.mjs +282 -0
- package/dist/mjs/subtle-crypto.mjs.map +10 -0
- package/dist/mjs/types.mjs +3 -0
- package/dist/mjs/types.mjs.map +9 -0
- package/dist/types/crypto-key.d.ts +10 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/quickjs.d.ts +287 -0
- package/dist/types/random.d.ts +14 -0
- package/dist/types/setup.d.ts +43 -0
- package/dist/types/subtle-crypto.d.ts +12 -0
- package/dist/types/types.d.ts +44 -0
- package/package.json +54 -6
package/README.md
CHANGED
|
@@ -1,45 +1,75 @@
|
|
|
1
1
|
# @ricsam/quickjs-crypto
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
3
|
+
Web Crypto API implementation providing cryptographic operations.
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import { setupCrypto } from "@ricsam/quickjs-crypto";
|
|
7
|
+
|
|
8
|
+
const handle = setupCrypto(context);
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Injected Globals:**
|
|
12
|
+
- `crypto.getRandomValues(array)` - Fill a TypedArray with random bytes
|
|
13
|
+
- `crypto.randomUUID()` - Generate a random UUID v4
|
|
14
|
+
- `crypto.subtle` - SubtleCrypto interface for cryptographic operations
|
|
15
|
+
|
|
16
|
+
**Usage in QuickJS:**
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
// Generate random bytes
|
|
20
|
+
const bytes = new Uint8Array(16);
|
|
21
|
+
crypto.getRandomValues(bytes);
|
|
22
|
+
|
|
23
|
+
// Generate UUID
|
|
24
|
+
const uuid = crypto.randomUUID();
|
|
25
|
+
console.log(uuid); // "550e8400-e29b-41d4-a716-446655440000"
|
|
26
|
+
|
|
27
|
+
// Hash data with SHA-256
|
|
28
|
+
const data = new TextEncoder().encode("Hello, World!");
|
|
29
|
+
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
30
|
+
|
|
31
|
+
// Generate encryption key
|
|
32
|
+
const key = await crypto.subtle.generateKey(
|
|
33
|
+
{ name: "AES-GCM", length: 256 },
|
|
34
|
+
true,
|
|
35
|
+
["encrypt", "decrypt"]
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// Encrypt data
|
|
39
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
40
|
+
const encrypted = await crypto.subtle.encrypt(
|
|
41
|
+
{ name: "AES-GCM", iv },
|
|
42
|
+
key,
|
|
43
|
+
data
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// Decrypt data
|
|
47
|
+
const decrypted = await crypto.subtle.decrypt(
|
|
48
|
+
{ name: "AES-GCM", iv },
|
|
49
|
+
key,
|
|
50
|
+
encrypted
|
|
51
|
+
);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### SubtleCrypto Methods
|
|
55
|
+
|
|
56
|
+
| Method | Description |
|
|
57
|
+
|--------|-------------|
|
|
58
|
+
| `digest` | Generate hash (SHA-256, SHA-384, SHA-512) |
|
|
59
|
+
| `generateKey` | Generate symmetric or asymmetric keys |
|
|
60
|
+
| `sign` / `verify` | Sign and verify data (HMAC, ECDSA) |
|
|
61
|
+
| `encrypt` / `decrypt` | Encrypt and decrypt data (AES-GCM, AES-CBC) |
|
|
62
|
+
| `importKey` / `exportKey` | Import/export keys (raw, jwk, pkcs8, spki) |
|
|
63
|
+
| `deriveBits` / `deriveKey` | Derive keys (PBKDF2, ECDH) |
|
|
64
|
+
| `wrapKey` / `unwrapKey` | Wrap/unwrap keys for secure transport |
|
|
65
|
+
|
|
66
|
+
**Supported Algorithms:**
|
|
67
|
+
- **Encryption**: AES-GCM, AES-CBC
|
|
68
|
+
- **Signing**: HMAC, ECDSA
|
|
69
|
+
- **Hashing**: SHA-256, SHA-384, SHA-512
|
|
70
|
+
- **Key Derivation**: PBKDF2, ECDH
|
|
71
|
+
- **Asymmetric**: ECDSA (P-256, P-384, P-521), RSA-OAEP
|
|
72
|
+
|
|
73
|
+
> **Note**: Cryptographic operations are delegated to the host's native `crypto.subtle` implementation, ensuring secure and performant cryptography.
|
|
74
|
+
|
|
75
|
+
**See also:** [MDN Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// @bun @bun-cjs
|
|
2
|
+
(function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
7
|
+
var __toCommonJS = (from) => {
|
|
8
|
+
var entry = __moduleCache.get(from), desc;
|
|
9
|
+
if (entry)
|
|
10
|
+
return entry;
|
|
11
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
13
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
14
|
+
get: () => from[key],
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
}));
|
|
17
|
+
__moduleCache.set(from, entry);
|
|
18
|
+
return entry;
|
|
19
|
+
};
|
|
20
|
+
var __export = (target, all) => {
|
|
21
|
+
for (var name in all)
|
|
22
|
+
__defProp(target, name, {
|
|
23
|
+
get: all[name],
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
set: (newValue) => all[name] = () => newValue
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// packages/crypto/src/crypto-key.ts
|
|
31
|
+
var exports_crypto_key = {};
|
|
32
|
+
__export(exports_crypto_key, {
|
|
33
|
+
createCryptoKeyClass: () => createCryptoKeyClass
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(exports_crypto_key);
|
|
36
|
+
var import_quickjs_core = require("@ricsam/quickjs-core");
|
|
37
|
+
function createCryptoKeyClass(context, stateMap) {
|
|
38
|
+
return import_quickjs_core.defineClass(context, stateMap, {
|
|
39
|
+
name: "CryptoKey",
|
|
40
|
+
construct: () => {
|
|
41
|
+
throw new Error("CryptoKey cannot be constructed directly. Use crypto.subtle methods instead.");
|
|
42
|
+
},
|
|
43
|
+
properties: {
|
|
44
|
+
type: {
|
|
45
|
+
get() {
|
|
46
|
+
return this.type;
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
extractable: {
|
|
50
|
+
get() {
|
|
51
|
+
return this.extractable;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
algorithm: {
|
|
55
|
+
get() {
|
|
56
|
+
return { ...this.algorithm };
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
usages: {
|
|
60
|
+
get() {
|
|
61
|
+
return [...this.usages];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
methods: {}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
//# debugId=81B8AC89A261F3CD64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/crypto-key.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { StateMap, CryptoKeyState } from \"./types.cjs\";\nimport { defineClass } from \"@ricsam/quickjs-core\";\n\n/**\n * Create the CryptoKey class for the QuickJS context\n *\n * CryptoKey is an opaque type - the actual key material stays on the host.\n * The QuickJS instance only holds metadata and an instanceId that maps\n * to the host-side CryptoKey.\n */\nexport function createCryptoKeyClass(\n context: QuickJSContext,\n stateMap: StateMap\n): QuickJSHandle {\n return defineClass<CryptoKeyState>(context, stateMap, {\n name: \"CryptoKey\",\n // CryptoKey cannot be constructed directly - only via SubtleCrypto methods\n construct: () => {\n throw new Error(\n \"CryptoKey cannot be constructed directly. Use crypto.subtle methods instead.\"\n );\n },\n properties: {\n type: {\n get(this: CryptoKeyState) {\n return this.type;\n },\n },\n extractable: {\n get(this: CryptoKeyState) {\n return this.extractable;\n },\n },\n algorithm: {\n get(this: CryptoKeyState) {\n // Return a copy of the algorithm object to prevent mutation\n return { ...this.algorithm };\n },\n },\n usages: {\n get(this: CryptoKeyState) {\n // Return a copy of usages array to prevent mutation\n return [...this.usages];\n },\n },\n },\n methods: {},\n });\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE4B,IAA5B;AASO,SAAS,oBAAoB,CAClC,SACA,UACe;AAAA,EACf,OAAO,gCAA4B,SAAS,UAAU;AAAA,IACpD,MAAM;AAAA,IAEN,WAAW,MAAM;AAAA,MACf,MAAM,IAAI,MACR,8EACF;AAAA;AAAA,IAEF,YAAY;AAAA,MACV,MAAM;AAAA,QACJ,GAAG,GAAuB;AAAA,UACxB,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,MACA,aAAa;AAAA,QACX,GAAG,GAAuB;AAAA,UACxB,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,MACA,WAAW;AAAA,QACT,GAAG,GAAuB;AAAA,UAExB,OAAO,KAAK,KAAK,UAAU;AAAA;AAAA,MAE/B;AAAA,MACA,QAAQ;AAAA,QACN,GAAG,GAAuB;AAAA,UAExB,OAAO,CAAC,GAAG,KAAK,MAAM;AAAA;AAAA,MAE1B;AAAA,IACF;AAAA,IACA,SAAS,CAAC;AAAA,EACZ,CAAC;AAAA;",
|
|
8
|
+
"debugId": "81B8AC89A261F3CD64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// @bun @bun-cjs
|
|
2
|
+
(function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
7
|
+
var __toCommonJS = (from) => {
|
|
8
|
+
var entry = __moduleCache.get(from), desc;
|
|
9
|
+
if (entry)
|
|
10
|
+
return entry;
|
|
11
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
13
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
14
|
+
get: () => from[key],
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
}));
|
|
17
|
+
__moduleCache.set(from, entry);
|
|
18
|
+
return entry;
|
|
19
|
+
};
|
|
20
|
+
var __export = (target, all) => {
|
|
21
|
+
for (var name in all)
|
|
22
|
+
__defProp(target, name, {
|
|
23
|
+
get: all[name],
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
set: (newValue) => all[name] = () => newValue
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// packages/crypto/src/index.ts
|
|
31
|
+
var exports_src = {};
|
|
32
|
+
__export(exports_src, {
|
|
33
|
+
setupCrypto: () => import_setup.setupCrypto,
|
|
34
|
+
createCryptoKeyInstance: () => import_subtle_crypto.createCryptoKeyInstance
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(exports_src);
|
|
37
|
+
var import_setup = require("./setup.cjs");
|
|
38
|
+
var import_subtle_crypto = require("./subtle-crypto.cjs");
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
//# debugId=DC10B513FF821FAB64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"export { setupCrypto } from \"./setup.cjs\";\nexport type {\n SetupCryptoOptions,\n CryptoHandle,\n CryptoKeyState,\n KeyUsage,\n KeyType,\n} from \"./types.cjs\";\nexport { createCryptoKeyInstance } from \"./subtle-crypto.cjs\";\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAA4B,IAA5B;AAQwC,IAAxC;",
|
|
8
|
+
"debugId": "DC10B513FF821FAB64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// @bun @bun-cjs
|
|
2
|
+
(function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
7
|
+
var __toCommonJS = (from) => {
|
|
8
|
+
var entry = __moduleCache.get(from), desc;
|
|
9
|
+
if (entry)
|
|
10
|
+
return entry;
|
|
11
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
13
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
14
|
+
get: () => from[key],
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
}));
|
|
17
|
+
__moduleCache.set(from, entry);
|
|
18
|
+
return entry;
|
|
19
|
+
};
|
|
20
|
+
var __export = (target, all) => {
|
|
21
|
+
for (var name in all)
|
|
22
|
+
__defProp(target, name, {
|
|
23
|
+
get: all[name],
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
set: (newValue) => all[name] = () => newValue
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// packages/crypto/src/random.ts
|
|
31
|
+
var exports_random = {};
|
|
32
|
+
__export(exports_random, {
|
|
33
|
+
createRandomUUIDFunction: () => createRandomUUIDFunction,
|
|
34
|
+
createGetRandomValuesFunction: () => createGetRandomValuesFunction
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(exports_random);
|
|
37
|
+
var import_quickjs_core = require("@ricsam/quickjs-core");
|
|
38
|
+
function createGetRandomValuesFunction(context) {
|
|
39
|
+
return context.newFunction("getRandomValues", (arrayHandle) => {
|
|
40
|
+
const byteLengthHandle = context.getProp(arrayHandle, "byteLength");
|
|
41
|
+
const byteLengthType = context.typeof(byteLengthHandle);
|
|
42
|
+
if (byteLengthType !== "number") {
|
|
43
|
+
byteLengthHandle.dispose();
|
|
44
|
+
throw context.newError("getRandomValues: argument must be an integer-typed TypedArray");
|
|
45
|
+
}
|
|
46
|
+
const byteLength = context.getNumber(byteLengthHandle);
|
|
47
|
+
byteLengthHandle.dispose();
|
|
48
|
+
if (byteLength > 65536) {
|
|
49
|
+
throw context.newError("getRandomValues: quota exceeded (max 65536 bytes)");
|
|
50
|
+
}
|
|
51
|
+
const randomBytes = new Uint8Array(byteLength);
|
|
52
|
+
crypto.getRandomValues(randomBytes);
|
|
53
|
+
const bytesArray = Array.from(randomBytes);
|
|
54
|
+
const setValuesResult = context.evalCode(`
|
|
55
|
+
(function(typedArray, bytes) {
|
|
56
|
+
const view = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
|
|
57
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
58
|
+
view[i] = bytes[i];
|
|
59
|
+
}
|
|
60
|
+
return typedArray;
|
|
61
|
+
})
|
|
62
|
+
`);
|
|
63
|
+
if (setValuesResult.error) {
|
|
64
|
+
const err = context.dump(setValuesResult.error);
|
|
65
|
+
setValuesResult.error.dispose();
|
|
66
|
+
throw context.newError(`getRandomValues failed: ${JSON.stringify(err)}`);
|
|
67
|
+
}
|
|
68
|
+
const setValuesFn = setValuesResult.value;
|
|
69
|
+
const bytesHandle = import_quickjs_core.marshal(context, bytesArray);
|
|
70
|
+
const result = context.callFunction(setValuesFn, context.undefined, arrayHandle, bytesHandle);
|
|
71
|
+
setValuesFn.dispose();
|
|
72
|
+
bytesHandle.dispose();
|
|
73
|
+
if (result.error) {
|
|
74
|
+
const err = context.dump(result.error);
|
|
75
|
+
result.error.dispose();
|
|
76
|
+
throw context.newError(`getRandomValues failed: ${JSON.stringify(err)}`);
|
|
77
|
+
}
|
|
78
|
+
return result.value;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function createRandomUUIDFunction(context) {
|
|
82
|
+
return context.newFunction("randomUUID", () => {
|
|
83
|
+
const uuid = crypto.randomUUID();
|
|
84
|
+
return context.newString(uuid);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
//# debugId=329C68AB71213A6764756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/random.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport { marshal } from \"@ricsam/quickjs-core\";\n\n/**\n * Create the getRandomValues function for the crypto global\n *\n * getRandomValues fills a TypedArray with cryptographically random values\n * and returns the same array (modified in-place)\n */\nexport function createGetRandomValuesFunction(\n context: QuickJSContext\n): QuickJSHandle {\n return context.newFunction(\"getRandomValues\", (arrayHandle) => {\n // Get byteLength to determine how many random bytes we need\n const byteLengthHandle = context.getProp(arrayHandle, \"byteLength\");\n const byteLengthType = context.typeof(byteLengthHandle);\n\n if (byteLengthType !== \"number\") {\n byteLengthHandle.dispose();\n throw context.newError(\n \"getRandomValues: argument must be an integer-typed TypedArray\"\n );\n }\n\n const byteLength = context.getNumber(byteLengthHandle);\n byteLengthHandle.dispose();\n\n if (byteLength > 65536) {\n throw context.newError(\n \"getRandomValues: quota exceeded (max 65536 bytes)\"\n );\n }\n\n // Generate random bytes on the host\n const randomBytes = new Uint8Array(byteLength);\n crypto.getRandomValues(randomBytes);\n\n // Convert to array of numbers for JSON serialization\n const bytesArray = Array.from(randomBytes);\n\n // Use evalCode to copy the bytes into the TypedArray\n // We pass the array handle and use a helper to set the values\n const setValuesResult = context.evalCode(`\n (function(typedArray, bytes) {\n const view = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);\n for (let i = 0; i < bytes.length; i++) {\n view[i] = bytes[i];\n }\n return typedArray;\n })\n `);\n\n if (setValuesResult.error) {\n const err = context.dump(setValuesResult.error);\n setValuesResult.error.dispose();\n throw context.newError(`getRandomValues failed: ${JSON.stringify(err)}`);\n }\n\n const setValuesFn = setValuesResult.value;\n const bytesHandle = marshal(context, bytesArray);\n\n const result = context.callFunction(\n setValuesFn,\n context.undefined,\n arrayHandle,\n bytesHandle\n );\n\n setValuesFn.dispose();\n bytesHandle.dispose();\n\n if (result.error) {\n const err = context.dump(result.error);\n result.error.dispose();\n throw context.newError(`getRandomValues failed: ${JSON.stringify(err)}`);\n }\n\n return result.value;\n });\n}\n\n/**\n * Create the randomUUID function for the crypto global\n *\n * randomUUID returns a string containing a randomly generated UUID v4\n */\nexport function createRandomUUIDFunction(\n context: QuickJSContext\n): QuickJSHandle {\n return context.newFunction(\"randomUUID\", () => {\n const uuid = crypto.randomUUID();\n return context.newString(uuid);\n });\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACwB,IAAxB;AAQO,SAAS,6BAA6B,CAC3C,SACe;AAAA,EACf,OAAO,QAAQ,YAAY,mBAAmB,CAAC,gBAAgB;AAAA,IAE7D,MAAM,mBAAmB,QAAQ,QAAQ,aAAa,YAAY;AAAA,IAClE,MAAM,iBAAiB,QAAQ,OAAO,gBAAgB;AAAA,IAEtD,IAAI,mBAAmB,UAAU;AAAA,MAC/B,iBAAiB,QAAQ;AAAA,MACzB,MAAM,QAAQ,SACZ,+DACF;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,QAAQ,UAAU,gBAAgB;AAAA,IACrD,iBAAiB,QAAQ;AAAA,IAEzB,IAAI,aAAa,OAAO;AAAA,MACtB,MAAM,QAAQ,SACZ,mDACF;AAAA,IACF;AAAA,IAGA,MAAM,cAAc,IAAI,WAAW,UAAU;AAAA,IAC7C,OAAO,gBAAgB,WAAW;AAAA,IAGlC,MAAM,aAAa,MAAM,KAAK,WAAW;AAAA,IAIzC,MAAM,kBAAkB,QAAQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAQxC;AAAA,IAED,IAAI,gBAAgB,OAAO;AAAA,MACzB,MAAM,MAAM,QAAQ,KAAK,gBAAgB,KAAK;AAAA,MAC9C,gBAAgB,MAAM,QAAQ;AAAA,MAC9B,MAAM,QAAQ,SAAS,2BAA2B,KAAK,UAAU,GAAG,GAAG;AAAA,IACzE;AAAA,IAEA,MAAM,cAAc,gBAAgB;AAAA,IACpC,MAAM,cAAc,4BAAQ,SAAS,UAAU;AAAA,IAE/C,MAAM,SAAS,QAAQ,aACrB,aACA,QAAQ,WACR,aACA,WACF;AAAA,IAEA,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,IAEpB,IAAI,OAAO,OAAO;AAAA,MAChB,MAAM,MAAM,QAAQ,KAAK,OAAO,KAAK;AAAA,MACrC,OAAO,MAAM,QAAQ;AAAA,MACrB,MAAM,QAAQ,SAAS,2BAA2B,KAAK,UAAU,GAAG,GAAG;AAAA,IACzE;AAAA,IAEA,OAAO,OAAO;AAAA,GACf;AAAA;AAQI,SAAS,wBAAwB,CACtC,SACe;AAAA,EACf,OAAO,QAAQ,YAAY,cAAc,MAAM;AAAA,IAC7C,MAAM,OAAO,OAAO,WAAW;AAAA,IAC/B,OAAO,QAAQ,UAAU,IAAI;AAAA,GAC9B;AAAA;",
|
|
8
|
+
"debugId": "329C68AB71213A6764756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// @bun @bun-cjs
|
|
2
|
+
(function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
7
|
+
var __toCommonJS = (from) => {
|
|
8
|
+
var entry = __moduleCache.get(from), desc;
|
|
9
|
+
if (entry)
|
|
10
|
+
return entry;
|
|
11
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
13
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
14
|
+
get: () => from[key],
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
}));
|
|
17
|
+
__moduleCache.set(from, entry);
|
|
18
|
+
return entry;
|
|
19
|
+
};
|
|
20
|
+
var __export = (target, all) => {
|
|
21
|
+
for (var name in all)
|
|
22
|
+
__defProp(target, name, {
|
|
23
|
+
get: all[name],
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
set: (newValue) => all[name] = () => newValue
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// packages/crypto/src/setup.ts
|
|
31
|
+
var exports_setup = {};
|
|
32
|
+
__export(exports_setup, {
|
|
33
|
+
setupCrypto: () => setupCrypto
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(exports_setup);
|
|
36
|
+
var import_quickjs_core = require("@ricsam/quickjs-core");
|
|
37
|
+
var import_crypto_key = require("./crypto-key.cjs");
|
|
38
|
+
var import_subtle_crypto = require("./subtle-crypto.cjs");
|
|
39
|
+
var import_random = require("./random.cjs");
|
|
40
|
+
function setupCrypto(context, options = {}) {
|
|
41
|
+
const coreHandle = options.coreHandle ?? import_quickjs_core.setupCore(context, { stateMap: options.stateMap });
|
|
42
|
+
const stateMap = options.stateMap ?? coreHandle.stateMap;
|
|
43
|
+
const CryptoKeyClass = import_crypto_key.createCryptoKeyClass(context, stateMap);
|
|
44
|
+
context.setProp(context.global, "CryptoKey", CryptoKeyClass);
|
|
45
|
+
CryptoKeyClass.dispose();
|
|
46
|
+
const subtleCrypto = import_subtle_crypto.createSubtleCryptoObject(context);
|
|
47
|
+
const cryptoObj = context.newObject();
|
|
48
|
+
const subtlePropResult = context.evalCode(`
|
|
49
|
+
(function(crypto, subtle) {
|
|
50
|
+
Object.defineProperty(crypto, 'subtle', {
|
|
51
|
+
value: subtle,
|
|
52
|
+
writable: false,
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: false
|
|
55
|
+
});
|
|
56
|
+
})
|
|
57
|
+
`);
|
|
58
|
+
if (subtlePropResult.error) {
|
|
59
|
+
const err = context.dump(subtlePropResult.error);
|
|
60
|
+
subtlePropResult.error.dispose();
|
|
61
|
+
throw new Error(`Failed to setup crypto.subtle: ${JSON.stringify(err)}`);
|
|
62
|
+
}
|
|
63
|
+
const defineSubtleFn = subtlePropResult.value;
|
|
64
|
+
const defineResult = context.callFunction(defineSubtleFn, context.undefined, cryptoObj, subtleCrypto);
|
|
65
|
+
defineSubtleFn.dispose();
|
|
66
|
+
subtleCrypto.dispose();
|
|
67
|
+
if (defineResult.error) {
|
|
68
|
+
const err = context.dump(defineResult.error);
|
|
69
|
+
defineResult.error.dispose();
|
|
70
|
+
throw new Error(`Failed to setup crypto.subtle: ${JSON.stringify(err)}`);
|
|
71
|
+
}
|
|
72
|
+
defineResult.value.dispose();
|
|
73
|
+
const getRandomValuesFn = import_random.createGetRandomValuesFunction(context);
|
|
74
|
+
context.setProp(cryptoObj, "getRandomValues", getRandomValuesFn);
|
|
75
|
+
getRandomValuesFn.dispose();
|
|
76
|
+
const randomUUIDFn = import_random.createRandomUUIDFunction(context);
|
|
77
|
+
context.setProp(cryptoObj, "randomUUID", randomUUIDFn);
|
|
78
|
+
randomUUIDFn.dispose();
|
|
79
|
+
context.setProp(context.global, "crypto", cryptoObj);
|
|
80
|
+
cryptoObj.dispose();
|
|
81
|
+
return {
|
|
82
|
+
stateMap,
|
|
83
|
+
dispose() {}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
//# debugId=FF7624FEEF73AF1964756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/setup.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { QuickJSContext } from \"quickjs-emscripten\";\nimport { setupCore, createStateMap } from \"@ricsam/quickjs-core\";\nimport type { SetupCryptoOptions, CryptoHandle } from \"./types.cjs\";\nimport { createCryptoKeyClass } from \"./crypto-key.cjs\";\nimport { createSubtleCryptoObject } from \"./subtle-crypto.cjs\";\nimport {\n createGetRandomValuesFunction,\n createRandomUUIDFunction,\n} from \"./random.cjs\";\n\n/**\n * Setup crypto globals in a QuickJS context\n *\n * Provides: crypto.subtle (SubtleCrypto), crypto.getRandomValues, crypto.randomUUID, CryptoKey\n *\n * @example\n * ```typescript\n * const handle = setupCrypto(context);\n *\n * context.evalCode(`\n * // Generate a random UUID\n * const uuid = crypto.randomUUID();\n *\n * // Generate random bytes\n * const arr = new Uint8Array(16);\n * crypto.getRandomValues(arr);\n *\n * // Use SubtleCrypto for encryption\n * const key = await crypto.subtle.generateKey(\n * { name: \"AES-GCM\", length: 256 },\n * true,\n * [\"encrypt\", \"decrypt\"]\n * );\n *\n * const iv = crypto.getRandomValues(new Uint8Array(12));\n * const data = new TextEncoder().encode(\"secret message\");\n * const encrypted = await crypto.subtle.encrypt(\n * { name: \"AES-GCM\", iv },\n * key,\n * data\n * );\n * `);\n *\n * handle.dispose();\n * ```\n *\n * @param context - QuickJS context\n * @param options - Setup options\n * @returns CryptoHandle for cleanup\n */\nexport function setupCrypto(\n context: QuickJSContext,\n options: SetupCryptoOptions = {}\n): CryptoHandle {\n // Setup core if not provided (needed for marshal/unmarshal infrastructure)\n const coreHandle =\n options.coreHandle ?? setupCore(context, { stateMap: options.stateMap });\n const stateMap = options.stateMap ?? coreHandle.stateMap;\n\n // 1. Create and register CryptoKey class (needed by SubtleCrypto)\n const CryptoKeyClass = createCryptoKeyClass(context, stateMap);\n context.setProp(context.global, \"CryptoKey\", CryptoKeyClass);\n CryptoKeyClass.dispose();\n\n // 2. Create the SubtleCrypto object\n const subtleCrypto = createSubtleCryptoObject(context);\n\n // 3. Create the crypto global object\n const cryptoObj = context.newObject();\n\n // Set subtle as a non-writable property\n const subtlePropResult = context.evalCode(`\n (function(crypto, subtle) {\n Object.defineProperty(crypto, 'subtle', {\n value: subtle,\n writable: false,\n enumerable: true,\n configurable: false\n });\n })\n `);\n\n if (subtlePropResult.error) {\n const err = context.dump(subtlePropResult.error);\n subtlePropResult.error.dispose();\n throw new Error(`Failed to setup crypto.subtle: ${JSON.stringify(err)}`);\n }\n\n const defineSubtleFn = subtlePropResult.value;\n const defineResult = context.callFunction(\n defineSubtleFn,\n context.undefined,\n cryptoObj,\n subtleCrypto\n );\n defineSubtleFn.dispose();\n subtleCrypto.dispose();\n\n if (defineResult.error) {\n const err = context.dump(defineResult.error);\n defineResult.error.dispose();\n throw new Error(`Failed to setup crypto.subtle: ${JSON.stringify(err)}`);\n }\n defineResult.value.dispose();\n\n // 4. Set getRandomValues on crypto object\n const getRandomValuesFn = createGetRandomValuesFunction(context);\n context.setProp(cryptoObj, \"getRandomValues\", getRandomValuesFn);\n getRandomValuesFn.dispose();\n\n // 5. Set randomUUID on crypto object\n const randomUUIDFn = createRandomUUIDFunction(context);\n context.setProp(cryptoObj, \"randomUUID\", randomUUIDFn);\n randomUUIDFn.dispose();\n\n // 6. Set crypto on global\n context.setProp(context.global, \"crypto\", cryptoObj);\n cryptoObj.dispose();\n\n return {\n stateMap,\n dispose() {\n // Globals are owned by context.global, cleaned up by context.dispose()\n },\n };\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAC0C,IAA1C;AAEqC,IAArC;AACyC,IAAzC;AAIO,IAHP;AA6CO,SAAS,WAAW,CACzB,SACA,UAA8B,CAAC,GACjB;AAAA,EAEd,MAAM,aACJ,QAAQ,cAAc,8BAAU,SAAS,EAAE,UAAU,QAAQ,SAAS,CAAC;AAAA,EACzE,MAAM,WAAW,QAAQ,YAAY,WAAW;AAAA,EAGhD,MAAM,iBAAiB,uCAAqB,SAAS,QAAQ;AAAA,EAC7D,QAAQ,QAAQ,QAAQ,QAAQ,aAAa,cAAc;AAAA,EAC3D,eAAe,QAAQ;AAAA,EAGvB,MAAM,eAAe,8CAAyB,OAAO;AAAA,EAGrD,MAAM,YAAY,QAAQ,UAAU;AAAA,EAGpC,MAAM,mBAAmB,QAAQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASzC;AAAA,EAED,IAAI,iBAAiB,OAAO;AAAA,IAC1B,MAAM,MAAM,QAAQ,KAAK,iBAAiB,KAAK;AAAA,IAC/C,iBAAiB,MAAM,QAAQ;AAAA,IAC/B,MAAM,IAAI,MAAM,kCAAkC,KAAK,UAAU,GAAG,GAAG;AAAA,EACzE;AAAA,EAEA,MAAM,iBAAiB,iBAAiB;AAAA,EACxC,MAAM,eAAe,QAAQ,aAC3B,gBACA,QAAQ,WACR,WACA,YACF;AAAA,EACA,eAAe,QAAQ;AAAA,EACvB,aAAa,QAAQ;AAAA,EAErB,IAAI,aAAa,OAAO;AAAA,IACtB,MAAM,MAAM,QAAQ,KAAK,aAAa,KAAK;AAAA,IAC3C,aAAa,MAAM,QAAQ;AAAA,IAC3B,MAAM,IAAI,MAAM,kCAAkC,KAAK,UAAU,GAAG,GAAG;AAAA,EACzE;AAAA,EACA,aAAa,MAAM,QAAQ;AAAA,EAG3B,MAAM,oBAAoB,4CAA8B,OAAO;AAAA,EAC/D,QAAQ,QAAQ,WAAW,mBAAmB,iBAAiB;AAAA,EAC/D,kBAAkB,QAAQ;AAAA,EAG1B,MAAM,eAAe,uCAAyB,OAAO;AAAA,EACrD,QAAQ,QAAQ,WAAW,cAAc,YAAY;AAAA,EACrD,aAAa,QAAQ;AAAA,EAGrB,QAAQ,QAAQ,QAAQ,QAAQ,UAAU,SAAS;AAAA,EACnD,UAAU,QAAQ;AAAA,EAElB,OAAO;AAAA,IACL;AAAA,IACA,OAAO,GAAG;AAAA,EAGZ;AAAA;",
|
|
8
|
+
"debugId": "FF7624FEEF73AF1964756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|