subtle.mjs raw
1 // TinyJS Runtime — SubtleCrypto bridge (AES-CBC + random bytes)
2 // Service worker version — identical to main app, SubtleCrypto available in SW scope.
3
4 import { Slice } from './builtin.mjs';
5
6 function sliceToU8(s) {
7 if (s instanceof Uint8Array) return s;
8 const u = new Uint8Array(s.$length);
9 for (let i = 0; i < s.$length; i++) u[i] = s.$array[s.$offset + i];
10 return u;
11 }
12
13 function u8ToSlice(u8) {
14 const arr = new Array(u8.length);
15 for (let i = 0; i < u8.length; i++) arr[i] = u8[i];
16 return new Slice(arr, 0, u8.length, u8.length);
17 }
18
19 export function RandomBytes(dst) {
20 const u8 = new Uint8Array(dst.$length);
21 crypto.getRandomValues(u8);
22 for (let i = 0; i < dst.$length; i++) dst.$array[dst.$offset + i] = u8[i];
23 }
24
25 export function AESCBCEncrypt(key, iv, plaintext, fn) {
26 const k = sliceToU8(key), v = sliceToU8(iv), pt = sliceToU8(plaintext);
27 crypto.subtle.importKey('raw', k, { name: 'AES-CBC' }, false, ['encrypt'])
28 .then(ck => crypto.subtle.encrypt({ name: 'AES-CBC', iv: v }, ck, pt))
29 .then(buf => fn(u8ToSlice(new Uint8Array(buf))));
30 }
31
32 export function AESCBCDecrypt(key, iv, ciphertext, fn) {
33 const k = sliceToU8(key), v = sliceToU8(iv), ct = sliceToU8(ciphertext);
34 crypto.subtle.importKey('raw', k, { name: 'AES-CBC' }, false, ['decrypt'])
35 .then(ck => crypto.subtle.decrypt({ name: 'AES-CBC', iv: v }, ck, ct))
36 .then(buf => fn(u8ToSlice(new Uint8Array(buf))));
37 }
38