Skip to content

Instantly share code, notes, and snippets.

@jknezek-locktera
Created January 29, 2024 22:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jknezek-locktera/f355371af152b4469772ded0f20de314 to your computer and use it in GitHub Desktop.
Save jknezek-locktera/f355371af152b4469772ded0f20de314 to your computer and use it in GitHub Desktop.
WebKit postMessage(CryptoKey) reproduction
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width"/>
<title>Service Worker Bug Reproduction</title>
</head>
<body>
<script type="module">
navigator.serviceWorker.addEventListener('message', async (e) => {
console.log('message from service worker:', e.data);
const password_string = 'password';
const password_bytes = new TextEncoder().encode(password_string);
const password_key = await crypto.subtle.importKey('raw', password_bytes, 'PBKDF2', false, ['deriveKey']);
const salt = crypto.getRandomValues(new Uint8Array(16));
const derived_key = await crypto.subtle.deriveKey({
name: 'PBKDF2',
hash: 'SHA-512',
salt: salt,
iterations: 200_000, // 100ms
}, password_key, {
name: 'AES-GCM',
length: 256,
}, false, ['encrypt', 'decrypt']);
console.log('posting response:', derived_key);
e.data.postMessage(derived_key);
console.log('posting repsonse:', 'no key');
e.data.postMessage('no key');
});
const registration = await navigator.serviceWorker.register(new URL('./sw.js', window.location.href).pathname, { type: 'module' });
await registration.update();
await navigator.serviceWorker.ready;
const rsp = await fetch('sw.js');
console.log('response:', rsp);
</script>
</body>
</html>
self.addEventListener('install', (e) => {
e.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', (e) => {
e.waitUntil(self.clients.claim());
});
self.addEventListener('fetch', (e) => {
console.log('fetch event:', e);
e.respondWith((async () => {
const client = await self.clients.get(e.clientId);
if (!client) return await fetch(e.request);
const response_promise = new Promise(resolve => {
const channel = new MessageChannel();
channel.port1.onmessage = (e) => {
resolve(e.data);
};
client.postMessage(channel.port2, [channel.port2]);
});
const response = await response_promise;
console.log('response:', response);
return await fetch(e.request);
})());
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment