From a1b266c65fd379a4df443e834d229db27fb31bba Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2026 20:38:59 +0000 Subject: [PATCH 1/2] deps: bump StarlingMonkey to starlingmonkey-v0.5.0 Also raise the @bytecodealliance/weval floor to ^0.5.1 to match the weval version StarlingMonkey's cmake/weval.cmake now fetches. --- StarlingMonkey | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/StarlingMonkey b/StarlingMonkey index 9dda8ba7..cce4d3da 160000 --- a/StarlingMonkey +++ b/StarlingMonkey @@ -1 +1 @@ -Subproject commit 9dda8ba7fcda2e17c6795d402f0478cf4c1f7f37 +Subproject commit cce4d3dabbda5c142a34253d321189551bae872d diff --git a/package-lock.json b/package-lock.json index b78e8977..0e641e74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "dependencies": { "@bytecodealliance/jco": "^1.15.1", "@bytecodealliance/preview2-shim": "^0.29.0", - "@bytecodealliance/weval": "^0.5.0", + "@bytecodealliance/weval": "^0.5.1", "@bytecodealliance/wizer": "^10.0.0", "es-module-lexer": "^1.6.0", "oxc-parser": "^0.154.0" @@ -494,9 +494,9 @@ } }, "node_modules/@bytecodealliance/weval": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@bytecodealliance/weval/-/weval-0.5.0.tgz", - "integrity": "sha512-lIR6+enn52gcdMQM8C3YaNoUlzm90TRkJrIgiVky/hED81ezDjhnq+6Z4w0eSFf9C6b2nmdKUFwbp6q1PhiuIQ==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/weval/-/weval-0.5.1.tgz", + "integrity": "sha512-Hb8qRoF3b2UgkZqeDTzaTKGITa31KCLcoyfFstE/uO/aYVUyHweaNDchF4SNrPQfEpiBwRnMUilI4Jbbl8Hl6w==", "license": "Apache-2.0", "dependencies": { "@napi-rs/lzma": "^1.1.2", diff --git a/package.json b/package.json index ae6f6fdc..cbcea388 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "dependencies": { "@bytecodealliance/jco": "^1.15.1", "@bytecodealliance/preview2-shim": "^0.29.0", - "@bytecodealliance/weval": "^0.5.0", + "@bytecodealliance/weval": "^0.5.1", "@bytecodealliance/wizer": "^10.0.0", "es-module-lexer": "^1.6.0", "oxc-parser": "^0.154.0" From 123521577fe219c2ee23a46567f49880c3b8106e Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2026 20:39:00 +0000 Subject: [PATCH 2/2] test: add crypto-subtle case for PBKDF2 deriveBits and AES-CBC Exercises crypto.subtle.importKey/deriveBits (PBKDF2-SHA256) and importKey/encrypt/decrypt (AES-256-CBC) landed in StarlingMonkey v0.5.0, asserting against known-answer vectors. --- test/cases/crypto-subtle/source.js | 65 ++++++++++++++++++++++++++++++ test/cases/crypto-subtle/test.js | 25 ++++++++++++ test/cases/crypto-subtle/world.wit | 9 +++++ 3 files changed, 99 insertions(+) create mode 100644 test/cases/crypto-subtle/source.js create mode 100644 test/cases/crypto-subtle/test.js create mode 100644 test/cases/crypto-subtle/world.wit diff --git a/test/cases/crypto-subtle/source.js b/test/cases/crypto-subtle/source.js new file mode 100644 index 00000000..0c252802 --- /dev/null +++ b/test/cases/crypto-subtle/source.js @@ -0,0 +1,65 @@ +const encoder = new TextEncoder(); +const decoder = new TextDecoder(); + +function toHex(buffer) { + return Array.from(new Uint8Array(buffer), (b) => + b.toString(16).padStart(2, '0'), + ).join(''); +} + +function fromHex(hex) { + const out = new Uint8Array(hex.length / 2); + for (let i = 0; i < out.length; i++) { + out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); + } + return out; +} + +function importAesKey(key, usage) { + return crypto.subtle.importKey('raw', key, { name: 'AES-CBC' }, false, [ + usage, + ]); +} + +export const exports = { + async pbkdf2Sha256(password, salt, iterations, length) { + const key = await crypto.subtle.importKey( + 'raw', + encoder.encode(password), + 'PBKDF2', + false, + ['deriveBits'], + ); + const bits = await crypto.subtle.deriveBits( + { + name: 'PBKDF2', + hash: 'SHA-256', + salt: encoder.encode(salt), + iterations, + }, + key, + length, + ); + return toHex(bits); + }, + + async aesCbcEncrypt(key, iv, plaintext) { + const cryptoKey = await importAesKey(key, 'encrypt'); + const ciphertext = await crypto.subtle.encrypt( + { name: 'AES-CBC', iv }, + cryptoKey, + encoder.encode(plaintext), + ); + return toHex(ciphertext); + }, + + async aesCbcDecrypt(key, iv, ciphertext) { + const cryptoKey = await importAesKey(key, 'decrypt'); + const plaintext = await crypto.subtle.decrypt( + { name: 'AES-CBC', iv }, + cryptoKey, + fromHex(ciphertext), + ); + return decoder.decode(plaintext); + }, +}; diff --git a/test/cases/crypto-subtle/test.js b/test/cases/crypto-subtle/test.js new file mode 100644 index 00000000..180515d8 --- /dev/null +++ b/test/cases/crypto-subtle/test.js @@ -0,0 +1,25 @@ +import { strictEqual } from 'node:assert'; + +// Expected values computed with Node's crypto.pbkdf2Sync / createCipheriv. +const PBKDF2_SHA256_PASSWORD_SALT_1000_256 = + '632c2812e46d4604102ba7618e9d6d7d2f8128f6266b4a03264d2a0460b7dcb3'; + +const AES_KEY = Uint8Array.from({ length: 32 }, (_, i) => i); +const AES_IV = Uint8Array.from({ length: 16 }, (_, i) => 0xf0 + i); +const PLAINTEXT = 'ComponentizeJS on StarlingMonkey v0.5.0'; +const AES_256_CBC_CIPHERTEXT = + 'd6bf9b3184d17b8c5c442baea2bedf72562f2f644911d6f30ff228bbec182b1d' + + 'feca06a5be162d2a41ea85e29b152867'; + +export function test(instance) { + const { exports } = instance; + + strictEqual( + exports.pbkdf2Sha256('password', 'salt', 1000, 256), + PBKDF2_SHA256_PASSWORD_SALT_1000_256, + ); + + const ciphertext = exports.aesCbcEncrypt(AES_KEY, AES_IV, PLAINTEXT); + strictEqual(ciphertext, AES_256_CBC_CIPHERTEXT); + strictEqual(exports.aesCbcDecrypt(AES_KEY, AES_IV, ciphertext), PLAINTEXT); +} diff --git a/test/cases/crypto-subtle/world.wit b/test/cases/crypto-subtle/world.wit new file mode 100644 index 00000000..f4cf2797 --- /dev/null +++ b/test/cases/crypto-subtle/world.wit @@ -0,0 +1,9 @@ +package local:crypto-subtle; + +world crypto-subtle { + export exports: interface { + pbkdf2-sha256: func(password: string, salt: string, iterations: u32, length: u32) -> string; + aes-cbc-encrypt: func(key: list, iv: list, plaintext: string) -> string; + aes-cbc-decrypt: func(key: list, iv: list, ciphertext: string) -> string; + } +}