fix: encryption

This commit is contained in:
n 2025-04-07 11:46:39 +01:00
parent f2efd198f8
commit ad5babda43

@ -69,13 +69,55 @@ function initStandaloneKeypair(): { publicKey: string, secretKey: Uint8Array } {
* @param relay Optional relay for the response
* @returns Stringified Nostr event or null if conversion fails
*/
export function convertToEvent(
// Helper function for proper Web Crypto API encryption
async function encryptWithWebCrypto(data: string, key: string): Promise<string> {
// Convert text to bytes
const dataBytes = new TextEncoder().encode(data);
// Create a key from the provided key (using SHA-256 hash)
const keyMaterial = await crypto.subtle.digest(
'SHA-256',
new TextEncoder().encode(key)
);
// Import the key
const cryptoKey = await crypto.subtle.importKey(
'raw',
keyMaterial,
{ name: 'AES-GCM' },
false,
['encrypt']
);
// Generate random IV
const iv = crypto.getRandomValues(new Uint8Array(12));
// Encrypt the data
const encryptedData = await crypto.subtle.encrypt(
{
name: 'AES-GCM',
iv: iv
},
cryptoKey,
dataBytes
);
// Combine IV and ciphertext
const encryptedArray = new Uint8Array(iv.length + encryptedData.byteLength);
encryptedArray.set(iv);
encryptedArray.set(new Uint8Array(encryptedData), iv.length);
// Convert to base64 string
return btoa(String.fromCharCode.apply(null, Array.from(encryptedArray)));
}
export async function convertToEvent(
httpRequest: string,
pubkey: string,
serverPubkey: string,
decryptkey: string,
relayUrl?: string
): string | null {
): Promise<string | null> {
console.log("convertToEvent called with httpRequest:", httpRequest.substring(0, 50) + "...");
if (!httpRequest || httpRequest.trim() === '') {
@ -84,10 +126,9 @@ export function convertToEvent(
}
// Create a single kind 21120 event with encrypted HTTP request as content
// Following the specification in README.md using actual NIP-44 encryption
// Using Web Crypto API for proper encryption
// Use the nostr-login library for encryption
let encryptedContent = httpRequest;
let encryptedContent: string;
try {
// Convert server pubkey to hex if it's an npub
@ -108,64 +149,29 @@ export function convertToEvent(
throw new Error("Invalid server pubkey format. Must be a 64-character hex string.");
}
// Check for the most specific NIP-44 methods first, then fall back to more general ones
if (NostrLogin && NostrLogin.nip44 && NostrLogin.nip44.encrypt) {
console.log("Using NostrLogin.nip44.encrypt for encryption");
try {
const encrypted = NostrLogin.nip44.encrypt(httpRequest, serverPubkeyHex);
if (encrypted) {
encryptedContent = encrypted;
console.log("Successfully encrypted content with NostrLogin.nip44");
} else {
console.warn("NostrLogin.nip44 encryption returned null or undefined");
}
} catch (encryptError) {
console.error("Encryption error with NostrLogin.nip44:", encryptError);
}
} else if (NostrLogin && NostrLogin.nip04 && NostrLogin.nip04.encrypt) {
console.log("Using NostrLogin.nip04.encrypt for encryption");
try {
const encrypted = NostrLogin.nip04.encrypt(httpRequest, serverPubkeyHex);
if (encrypted) {
encryptedContent = encrypted;
console.log("Successfully encrypted content with NostrLogin.nip04");
} else {
console.warn("NostrLogin.nip04 encryption returned null or undefined");
}
} catch (encryptError) {
console.error("Encryption error with NostrLogin.nip04:", encryptError);
}
} else if (NostrLogin && NostrLogin.encrypt) {
console.log("Using NostrLogin.encrypt for encryption");
try {
const encrypted = NostrLogin.encrypt(httpRequest, serverPubkeyHex);
if (encrypted) {
encryptedContent = encrypted;
console.log("Successfully encrypted content with NostrLogin.encrypt");
} else {
console.warn("NostrLogin.encrypt returned null or undefined");
}
} catch (encryptError) {
console.error("Encryption error with NostrLogin.encrypt:", encryptError);
}
} else if (window.nostr && window.nostr.nip44) {
console.log("Falling back to window.nostr.nip44.encrypt");
try {
encryptedContent = window.nostr.nip44.encrypt(httpRequest, serverPubkeyHex);
console.log("Successfully encrypted content with window.nostr.nip44");
} catch (encryptError) {
console.error("Encryption error with window.nostr.nip44:", encryptError);
}
} else {
console.warn("No encryption method available. Using unencrypted content.");
}
// Create a payload object with the HTTP request
const payload = {
httpRequest: httpRequest,
timestamp: Date.now(),
serverPubkey: serverPubkeyHex
};
// Stringify the payload to encrypt
const payloadString = JSON.stringify(payload);
// Use Web Crypto API to encrypt the payload with decryptkey
console.log("Encrypting with Web Crypto API");
encryptedContent = await encryptWithWebCrypto(payloadString, decryptkey);
console.log("Successfully encrypted content with Web Crypto API");
} catch (error) {
console.error("Error in encryption setup:", error);
// Continue with unencrypted content
console.error("Error in encryption:", error);
// Fall back to unencrypted content if encryption fails
encryptedContent = httpRequest;
}
// Debug log the content
console.log("Final encryptedContent before creating event:", encryptedContent);
console.log("Final encryptedContent before creating event:",
encryptedContent.substring(0, 50) + "...");
// Convert serverPubkey to hex if it's an npub
let pTagValue = serverPubkey;
@ -277,7 +283,8 @@ export async function displayConvertedEvent(): Promise<void> {
console.log("Generated random encryption key:", randomKey);
const convertedEvent = convertToEvent(
// Call the async convertToEvent function and await its result
const convertedEvent = await convertToEvent(
requestToUse,
pubkey,
serverPubkey,