mirror of
https://github.com/aljazceru/ditto.git
synced 2026-01-30 18:44:20 +01:00
Merge branch 'wallet' into 'main'
Add an HD wallet See merge request soapbox-pub/ditto!532
This commit is contained in:
51
src/DittoWallet.ts
Normal file
51
src/DittoWallet.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { HDKey } from '@scure/bip32';
|
||||
|
||||
import { Conf } from '@/config.ts';
|
||||
|
||||
/**
|
||||
* HD wallet based on the `DITTO_NSEC`.
|
||||
* The wallet is used to derive keys for various purposes.
|
||||
* It is a singleton with static methods, and the keys are cached.
|
||||
*/
|
||||
export class DittoWallet {
|
||||
static #root = HDKey.fromMasterSeed(Conf.seckey);
|
||||
static #keys = new Map<string, HDKey>();
|
||||
|
||||
/** Derive the key cached. */
|
||||
static derive(path: string): HDKey {
|
||||
const existing = this.#keys.get(path);
|
||||
if (existing) {
|
||||
return existing;
|
||||
} else {
|
||||
const key = this.#root.derive(path);
|
||||
this.#keys.set(path, key);
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
/** Derive the key and return the bytes. */
|
||||
static deriveKey(path: string): Uint8Array {
|
||||
const { privateKey } = this.derive(path);
|
||||
|
||||
if (!privateKey) {
|
||||
throw new Error('Private key not available');
|
||||
}
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
/** Database encryption key for AES-GCM encryption of database columns. */
|
||||
static get dbKey(): Uint8Array {
|
||||
return this.deriveKey(Conf.wallet.dbKeyPath);
|
||||
}
|
||||
|
||||
/** Captcha encryption key for encrypting answer data in AES-GCM. */
|
||||
static get captchaKey(): Uint8Array {
|
||||
return this.deriveKey(Conf.wallet.captchaKeyPath);
|
||||
}
|
||||
|
||||
/** VAPID secret key, used for web push notifications. ES256. */
|
||||
static get vapidKey(): Uint8Array {
|
||||
return this.deriveKey(Conf.wallet.vapidKeyPath);
|
||||
}
|
||||
}
|
||||
@@ -99,6 +99,25 @@ class Conf {
|
||||
},
|
||||
},
|
||||
};
|
||||
/**
|
||||
* BIP-32 derivation paths for different crypto use-cases.
|
||||
* The `DITTO_NSEC` is used as the seed.
|
||||
* Keys can be rotated by changing the derviation path.
|
||||
*/
|
||||
static wallet = {
|
||||
/** Private key for AES-GCM encryption in the Postgres database. */
|
||||
get dbKeyPath(): string {
|
||||
return Deno.env.get('WALLET_DB_KEY_PATH') || "m/0'/1'";
|
||||
},
|
||||
/** Private key for AES-GCM encryption of captcha answer data. */
|
||||
get captchaKeyPath(): string {
|
||||
return Deno.env.get('WALLET_CAPTCHA_KEY_PATH') || "m/0'/2'";
|
||||
},
|
||||
/** VAPID private key path. */
|
||||
get vapidKeyPath(): string {
|
||||
return Deno.env.get('WALLET_VAPID_KEY_PATH') || "m/0'/3'";
|
||||
},
|
||||
};
|
||||
/** Character limit to enforce for posts made through Mastodon API. */
|
||||
static get postCharLimit(): number {
|
||||
return Number(Deno.env.get('POST_CHAR_LIMIT') || 5000);
|
||||
|
||||
Reference in New Issue
Block a user