-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: encrypt connection secret field
- Loading branch information
Showing
15 changed files
with
168 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
LOG_LEVEL=debug | ||
BASE_URL=http://localhost:8080 | ||
DATABASE_URL=postgresql://myuser:mypass@localhost:5432/alby_lite | ||
DATABASE_URL=postgresql://myuser:mypass@localhost:5432/alby_lite | ||
# generate using deno task db:generate:key | ||
ENCRYPTION_KEY= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { expect } from "jsr:@std/expect"; | ||
import { decrypt, encrypt } from "./aesgcm.ts"; | ||
|
||
const NWC_URL = | ||
"nostr+walletconnect://0ba9d3de7e3e201aad29ee6b9fca20da0e5fc638c4b0513671eaea9c16a3989f?relay=wss://relay.getalby.com/v1&secret=bdaec8619bcf63a7c797043092ef72a6f62270c0f832561faf8f51f0cfdfce33"; | ||
|
||
Deno.test("encrypt and decrypt with correct key", async () => { | ||
const plaintext = NWC_URL; | ||
const encrypted = await encrypt(plaintext); | ||
const encrypted2 = await encrypt(plaintext); | ||
expect(encrypted).not.toEqual(plaintext); | ||
expect(encrypted2).not.toEqual(encrypted); | ||
const decrypted = await decrypt(encrypted); | ||
expect(decrypted).toEqual(plaintext); | ||
}); | ||
|
||
Deno.test("cannot decrypt with incorrect key", async () => { | ||
const plaintext = NWC_URL; | ||
const encrypted = await encrypt(plaintext); | ||
try { | ||
const incorrectKey = await crypto.subtle.generateKey( | ||
{ | ||
name: "AES-GCM", | ||
length: 256, // Can be 128, 192, or 256 | ||
}, | ||
true, // extractable | ||
["encrypt", "decrypt"] | ||
); | ||
await decrypt(encrypted, incorrectKey); | ||
// should never get here | ||
expect(true).toBe(false); | ||
} catch (error) { | ||
expect(error.toString()).toEqual("OperationError: Decryption failed"); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { Buffer } from "node:buffer"; | ||
|
||
const encryptionKeyBase64 = Deno.env.get("ENCRYPTION_KEY"); | ||
if (!encryptionKeyBase64) { | ||
console.log("no ENCRYPTION_KEY provided, exiting"); | ||
Deno.exit(1); | ||
} | ||
|
||
const encryptionKey = await crypto.subtle.importKey( | ||
"raw", | ||
Buffer.from(encryptionKeyBase64, "base64"), | ||
{ | ||
name: "AES-GCM", | ||
length: 256, // Can be 128, 192, or 256 | ||
}, | ||
true, // extractable | ||
["encrypt", "decrypt"] | ||
); | ||
|
||
const IV_LENGTH = 12; | ||
|
||
// Encrypt with random IV and prepend IV to ciphertext | ||
export async function encrypt( | ||
plaintext: string, | ||
key = encryptionKey | ||
): Promise<string> { | ||
const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH)); // Secure random IV | ||
|
||
const encoded = new TextEncoder().encode(plaintext); | ||
|
||
const ciphertext = await crypto.subtle.encrypt( | ||
{ | ||
name: "AES-GCM", | ||
iv: iv, | ||
}, | ||
key, | ||
encoded | ||
); | ||
|
||
// Combine IV and ciphertext | ||
const combined = new Uint8Array(iv.length + ciphertext.byteLength); | ||
combined.set(iv); | ||
combined.set(new Uint8Array(ciphertext), iv.length); | ||
|
||
return Buffer.from(combined.buffer).toString("base64"); | ||
} | ||
|
||
// Decrypt by extracting IV from the beginning of ciphertext | ||
export async function decrypt( | ||
combinedBase64: string, | ||
key = encryptionKey | ||
): Promise<string> { | ||
const combined = Buffer.from(combinedBase64, "base64"); | ||
|
||
const iv = combined.subarray(0, IV_LENGTH); // Extract first IV_LENGTH bytes as IV | ||
const ciphertext = combined.subarray(IV_LENGTH); | ||
|
||
const decrypted = await crypto.subtle.decrypt( | ||
{ | ||
name: "AES-GCM", | ||
iv: iv, | ||
}, | ||
key, | ||
ciphertext | ||
); | ||
|
||
const decoder = new TextDecoder(); | ||
return decoder.decode(decrypted); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Buffer } from "node:buffer"; | ||
console.log( | ||
Buffer.from( | ||
await crypto.subtle.exportKey( | ||
"raw", | ||
await crypto.subtle.generateKey( | ||
{ | ||
name: "AES-GCM", | ||
length: 256, | ||
}, | ||
true, | ||
["encrypt", "decrypt"] | ||
) | ||
) | ||
).toString("base64") | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters