diff --git a/contentScript.js b/contentScript.js index ab909d8..98b6f50 100644 --- a/contentScript.js +++ b/contentScript.js @@ -1,3 +1,178 @@ +async function generateKey() { + return await crypto.subtle.generateKey( + { + name: "ECDSA", + namedCurve: "P-256" + }, + true, // Whether the key is extractable (i.e., can be used outside the Crypto API) + ["sign", "verify"] // Can be used for signing and verification + ); +} + +// Convert the data (e.g., event hash) to an ArrayBuffer +function str2ab(str) { + const buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char + const bufView = new Uint16Array(buf); + for (let i = 0, strLen = str.length; i < strLen; i++) { + bufView[i] = str.charCodeAt(i); + } + return buf; +} + +// Sign the event hash +async function signEventHash(privateKey, eventHash) { + const encodedEventHash = str2ab(eventHash); + const signature = await crypto.subtle.sign( + { + name: "ECDSA", + hash: { name: "SHA-256" } // Choose the hash algorithm you want to use + }, + privateKey, + encodedEventHash // The data you want to sign + ); + return new Uint8Array(signature); +} + +function byteArrayTo64BytesHex(byteArray) { + // Convert the byte array to a hex string + let hex = Array.from(byteArray, function(byte) { + return ('0' + (byte & 0xFF).toString(16)).slice(-2); + }).join(''); + + // Ensure the hex string is exactly 128 characters long (64 bytes) + if (hex.length > 128) { + hex = hex.slice(0, 128); // Truncate if it's too long + } else { + hex = hex.padEnd(128, '0'); // Pad with zeros if it's too short + } + + return hex; +} + +function stringTo64BytesHex(str) { + // Convert the string to a hexadecimal string + let hex = Array.from(str, function(c) { + return c.charCodeAt(0).toString(16).padStart(2, '0'); + }).join(''); + + // Ensure the hex string is exactly 128 characters long (64 bytes) + if (hex.length > 128) { + hex = hex.slice(0, 128); // Truncate if it's too long + } else { + hex = hex.padEnd(128, '0'); // Pad with zeros if it's too short + } + + return hex; +} + +function stringTo32BytesHex(str) { + // Convert the string to a hexadecimal string + let hex = Array.from(str, function(c) { + return c.charCodeAt(0).toString(16).padStart(2, '0'); + }).join(''); + + // Ensure the hex string is exactly 64 characters long (32 bytes) + if (hex.length > 64) { + hex = hex.slice(0, 64); // Truncate if it's too long + } else { + hex = hex.padEnd(64, '0'); // Pad with zeros if it's too short + } + + return hex; +} + +const relayUrl = "wss://relay.sc24.steffen-roertgen.de"; +const socket = new WebSocket(relayUrl); +const publicKey = 'npub1r30l8j4vmppvq8w23umcyvd3vct4zmfpfkn4c7h2h057rmlfcrmq9xt9ma'; + +async function signEvent(event, privateKey) { + const eventHash = await hashEvent(event); // You need to create a hash of the event + const signature = await signEventHash(privateKey, eventHash); + event.sig = byteArrayTo64BytesHex(signature); + event.id = stringTo32BytesHex(eventHash); // The event ID is the hash of the event +} + +// Example function to hash an event +async function hashEvent(event) { + const eventString = JSON.stringify([event.pubkey, event.created_at, event.kind, event.tags, event.content]); + const encoder = new TextEncoder(); + const data = encoder.encode(eventString); + const hashBuffer = await crypto.subtle.digest('SHA-256', data); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + return hashArray.map(byte => byte.toString(16).padStart(2, '0')).join(''); +} + +// Send the event to the relay +async function sendEventToRelay(event) { + const privateKey = await generateKey(); + await signEvent(event, privateKey.privateKey); + + socket.send(JSON.stringify(["EVENT", event])); + console.log("Event sent to the relay:", event); + + socket.addEventListener('message', function (message) { + console.log("Received message from relay:", message.data); + }); + + socket.addEventListener('error', function (error) { + console.error("WebSocket error:", error); + }); + + socket.addEventListener('close', function () { + console.log("WebSocket connection closed"); + }); +} + +function findLDJSONScripts() { + const scripts = document.querySelectorAll('script[type="application/ld+json"]'); + const jsonData = []; + + scripts.forEach(script => { + try { + const json = JSON.parse(script.textContent); + jsonData.push(json); + } catch (e) { + console.error("Error parsing JSON-LD", e); + } + }); + + return jsonData; +} + +window.addEventListener('load', myMain); + +function myMain() { + console.log("DOM fully loaded and parsed"); + + const ldJsonData = findLDJSONScripts(); + + if (ldJsonData.length > 0) { + console.log(ldJsonData[0]) + const name1 = ldJsonData[0]['name'] + const description1 = ldJsonData[0]['description'] + const dlgtext = `${name1}\n\n${description1}\n\nSend nostr event to relay?` + const userConfirmed = confirm(dlgtext); + + if (userConfirmed) { + let event = { + id: '', // The ID of the event will be filled in after signing + pubkey: stringTo32BytesHex(publicKey), // Your public key + created_at: Math.floor(Date.now() / 1000), // Current timestamp in seconds + kind: 1, // Kind 1 usually refers to a "note" or text event + tags: [], // An array of tags (if any) + content: description1, // The message content + sig: '' // Signature will be added after signing + }; + sendEventToRelay(event); + alert('data sent to nostr relay') + + } + + } +} + + +/* // contentScript.js // Function to find and return the content of ld+json scripts @@ -52,4 +227,4 @@ function myMain() { // }); // Send the extracted JSON-LD data to the popup or render it directly //const ldJsonData = findLDJSONScripts(); - +*/ \ No newline at end of file