Clarify password role, random die, updated wording
All checks were successful
check / check (push) Successful in 14s
All checks were successful
check / check (push) Successful in 14s
- Password help text now explains it encrypts the recovery phrase on disk and is not used for address derivation - Die button generates cryptographically random phrases using crypto.getRandomValues(), different each click - "roll the die for a new one" wording - README documents full encryption scheme (PBKDF2 + AES-256-GCM) and explicitly notes password is not part of BIP-39 derivation
This commit is contained in:
20
README.md
20
README.md
@@ -201,12 +201,22 @@ want maximum privacy can point it at their own Ethereum node.
|
||||
|
||||
- **No framework**: The popup UI is vanilla JS and HTML. The extension is small
|
||||
enough that a framework adds unnecessary complexity and attack surface.
|
||||
- **Encrypted storage**: Seed phrases are encrypted with a user-provided
|
||||
password using AES-256-GCM before being stored in the extension's local
|
||||
storage. The encryption key is derived from the password using PBKDF2 with a
|
||||
high iteration count.
|
||||
- **Encrypted storage**: Recovery phrases and private keys are encrypted at rest
|
||||
in the extension's local storage. The encryption scheme:
|
||||
- The user's password is run through PBKDF2-SHA256 (600,000 iterations) with
|
||||
a random salt to derive a 256-bit encryption key.
|
||||
- The encryption key + a random IV encrypt the secret material using
|
||||
AES-256-GCM.
|
||||
- Stored blob: `{ salt, iv, ciphertext, authTag }`.
|
||||
- **The password is NOT used in address derivation.** It exists solely to
|
||||
protect the recovery phrase / private key on disk. Anyone with the
|
||||
recovery phrase can restore the wallet on any device without this
|
||||
password. This matches MetaMask's behavior.
|
||||
- **BIP-39 / BIP-44**: Standard mnemonic generation and HD key derivation
|
||||
(`m/44'/60'/0'/0/n`) for Ethereum address compatibility.
|
||||
(`m/44'/60'/0'/0/n`) for Ethereum address compatibility. The BIP-39 passphrase
|
||||
is always empty (matching MetaMask and most wallet software). The user's
|
||||
password is completely separate and has no effect on which addresses are
|
||||
generated.
|
||||
- **EIP-1193 provider**: The content script injects a `window.ethereum` object
|
||||
that implements the EIP-1193 provider interface, enabling web3 site
|
||||
connectivity.
|
||||
|
||||
@@ -56,8 +56,8 @@
|
||||
Add Wallet
|
||||
</h1>
|
||||
<p class="mb-2">
|
||||
Enter your 12 or 24 word recovery phrase below, or press the
|
||||
die to generate a new one.
|
||||
Enter your 12 or 24 word recovery phrase below, or click the
|
||||
button to roll the die for a new one.
|
||||
</p>
|
||||
<div class="mb-1 flex justify-end">
|
||||
<button
|
||||
@@ -88,8 +88,10 @@
|
||||
<div class="mb-2" id="add-wallet-password-section">
|
||||
<label class="block mb-1">Choose a password</label>
|
||||
<p class="text-xs text-muted mb-1">
|
||||
This password locks the wallet on this device. It is not
|
||||
the same as your recovery phrase.
|
||||
This password encrypts your recovery phrase on this
|
||||
device. It does not affect your wallet addresses or
|
||||
funds — anyone with your recovery phrase can restore
|
||||
your wallet without this password.
|
||||
</p>
|
||||
<input
|
||||
type="password"
|
||||
@@ -154,7 +156,9 @@
|
||||
<div class="mb-2" id="import-key-password-section">
|
||||
<label class="block mb-1">Choose a password</label>
|
||||
<p class="text-xs text-muted mb-1">
|
||||
This password locks the wallet on this device.
|
||||
This password encrypts your private key on this device.
|
||||
Anyone with your private key can access your funds
|
||||
without this password.
|
||||
</p>
|
||||
<input
|
||||
type="password"
|
||||
|
||||
@@ -70,9 +70,9 @@ function makeStubAddress() {
|
||||
};
|
||||
}
|
||||
|
||||
function generateStubMnemonic() {
|
||||
// TODO: replace with real BIP-39 generation via background
|
||||
const words = [
|
||||
// Stub wordlist for random phrase generation.
|
||||
// TODO: replace with real BIP-39 generation via background.
|
||||
const STUB_WORDLIST = [
|
||||
"abandon",
|
||||
"ability",
|
||||
"able",
|
||||
@@ -85,8 +85,138 @@ function generateStubMnemonic() {
|
||||
"abuse",
|
||||
"access",
|
||||
"accident",
|
||||
"account",
|
||||
"accuse",
|
||||
"achieve",
|
||||
"acid",
|
||||
"acoustic",
|
||||
"acquire",
|
||||
"across",
|
||||
"act",
|
||||
"action",
|
||||
"actor",
|
||||
"actual",
|
||||
"adapt",
|
||||
"add",
|
||||
"addict",
|
||||
"address",
|
||||
"adjust",
|
||||
"admit",
|
||||
"adult",
|
||||
"advance",
|
||||
"advice",
|
||||
"aerobic",
|
||||
"affair",
|
||||
"afford",
|
||||
"afraid",
|
||||
"again",
|
||||
"age",
|
||||
"agent",
|
||||
"agree",
|
||||
"ahead",
|
||||
"aim",
|
||||
"air",
|
||||
"airport",
|
||||
"aisle",
|
||||
"alarm",
|
||||
"album",
|
||||
"alcohol",
|
||||
"alert",
|
||||
"alien",
|
||||
"all",
|
||||
"alley",
|
||||
"allow",
|
||||
"almost",
|
||||
"alone",
|
||||
"alpha",
|
||||
"already",
|
||||
"also",
|
||||
"alter",
|
||||
"always",
|
||||
"amateur",
|
||||
"amazing",
|
||||
"among",
|
||||
"amount",
|
||||
"amused",
|
||||
"analyst",
|
||||
"anchor",
|
||||
"ancient",
|
||||
"anger",
|
||||
"angle",
|
||||
"angry",
|
||||
"animal",
|
||||
"ankle",
|
||||
"announce",
|
||||
"annual",
|
||||
"another",
|
||||
"answer",
|
||||
"antenna",
|
||||
"antique",
|
||||
"anxiety",
|
||||
"any",
|
||||
"apart",
|
||||
"apology",
|
||||
"appear",
|
||||
"apple",
|
||||
"approve",
|
||||
"april",
|
||||
"arch",
|
||||
"arctic",
|
||||
"area",
|
||||
"arena",
|
||||
"argue",
|
||||
"arm",
|
||||
"armed",
|
||||
"armor",
|
||||
"army",
|
||||
"around",
|
||||
"arrange",
|
||||
"arrest",
|
||||
"arrive",
|
||||
"arrow",
|
||||
"art",
|
||||
"artefact",
|
||||
"artist",
|
||||
"artwork",
|
||||
"ask",
|
||||
"aspect",
|
||||
"assault",
|
||||
"asset",
|
||||
"assist",
|
||||
"assume",
|
||||
"asthma",
|
||||
"athlete",
|
||||
"atom",
|
||||
"attack",
|
||||
"attend",
|
||||
"attitude",
|
||||
"attract",
|
||||
"auction",
|
||||
"audit",
|
||||
"august",
|
||||
"aunt",
|
||||
"author",
|
||||
"auto",
|
||||
"autumn",
|
||||
"average",
|
||||
"avocado",
|
||||
"avoid",
|
||||
"awake",
|
||||
"aware",
|
||||
"awesome",
|
||||
"awful",
|
||||
"awkward",
|
||||
"axis",
|
||||
];
|
||||
return words.join(" ");
|
||||
|
||||
function generateStubMnemonic() {
|
||||
const phrase = [];
|
||||
for (let i = 0; i < 12; i++) {
|
||||
const bytes = new Uint32Array(1);
|
||||
crypto.getRandomValues(bytes);
|
||||
phrase.push(STUB_WORDLIST[bytes[0] % STUB_WORDLIST.length]);
|
||||
}
|
||||
return phrase.join(" ");
|
||||
}
|
||||
|
||||
// -- render wallet list on main view --
|
||||
|
||||
Reference in New Issue
Block a user