Add ethers.js and libsodium, document crypto policy
All checks were successful
check / check (push) Successful in 21s

Runtime deps: ethers 6.16.0 (all Ethereum operations) and
libsodium-wrappers-sumo 0.8.2 (Argon2id + XSalsa20-Poly1305 for
encrypting secrets at rest). README now documents all dependencies
with versions/licenses, a crypto policy forbidding raw primitives
in application code, and the updated encryption scheme.
This commit is contained in:
2026-02-25 15:37:49 +07:00
parent e6d8f6acf4
commit a967029511
3 changed files with 132 additions and 21 deletions

View File

@@ -48,22 +48,18 @@ separate output directories.
src/ src/
background/ — service worker / background script background/ — service worker / background script
index.js — extension lifecycle, message routing index.js — extension lifecycle, message routing
wallet.js — wallet management (create, import, derive) wallet.js — wallet management (create, import, derive via ethers.js)
provider.js — EIP-1193 JSON-RPC provider implementation provider.js — EIP-1193 JSON-RPC provider implementation
transaction.js — transaction construction and signing
popup/ — popup UI (the main wallet interface) popup/ — popup UI (the main wallet interface)
index.html index.html
index.js index.js
components/ — UI components (account list, send form, etc.)
styles/ — CSS (Tailwind) styles/ — CSS (Tailwind)
content/ — content script injected into web pages content/ — content script injected into web pages
index.js — injects the provider into page context index.js — injects the provider into page context
inpage.js — the window.ethereum provider object inpage.js — the window.ethereum provider object
shared/ — shared utilities shared/ — shared utilities
crypto.js — BIP-39 mnemonic, HD key derivation, signing vault.js encrypted storage via libsodium
storage.js — encrypted storage abstraction
constants.js — chain IDs, default RPC endpoints, ERC-20 ABI constants.js — chain IDs, default RPC endpoints, ERC-20 ABI
rpc.js — JSON-RPC client for Ethereum nodes
manifest/ manifest/
chrome.json — Manifest V3 for Chrome chrome.json — Manifest V3 for Chrome
firefox.json — Manifest V2/V3 for Firefox firefox.json — Manifest V2/V3 for Firefox
@@ -197,32 +193,75 @@ What the extension does NOT do:
The user's RPC endpoint is the single point of external communication. Users who The user's RPC endpoint is the single point of external communication. Users who
want maximum privacy can point it at their own Ethereum node. want maximum privacy can point it at their own Ethereum node.
### Dependencies
AutistMask uses two runtime libraries. All cryptographic operations are
delegated to these libraries — see the Crypto Policy section below.
| Package | Version | License | Purpose |
| ------------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ethers` | 6.16.0 | MIT | All Ethereum operations: BIP-39 mnemonic generation/validation, BIP-32/BIP-44 HD key derivation (`m/44'/60'/0'/0/n`), secp256k1 signing, transaction construction, ERC-20 contract interaction, JSON-RPC communication, address derivation (keccak256). |
| `libsodium-wrappers-sumo` | 0.8.2 | ISC | Password-based encryption of secrets at rest: Argon2id key derivation (`crypto_pwhash`), authenticated encryption (`crypto_secretbox` / XSalsa20-Poly1305). |
Dev dependencies (not shipped in extension):
| Package | Version | License | Purpose |
| ------------------ | ------- | ------- | --------------- |
| `tailwindcss` | 4.2.1 | MIT | CSS compilation |
| `@tailwindcss/cli` | 4.2.1 | MIT | Tailwind CLI |
| `jest` | 30.2.0 | MIT | Test runner |
| `prettier` | 3.8.1 | MIT | Code formatter |
### Crypto Policy
**No raw crypto primitives in application code.** If the strings `aes`, `sha`,
`pbkdf`, `hmac`, `encrypt`, `decrypt`, `hash`, `cipher`, `digest`, `sign`
(case-insensitive) appear in our own source code (outside of `node_modules/`),
it is almost certainly a bug. All cryptographic operations must go through
`ethers` or `libsodium-wrappers-sumo`. This policy exists because:
- Rolling your own crypto is the single most common source of security
vulnerabilities in wallet software.
- Both libraries are widely audited and battle-tested.
- Keeping crypto out of application code makes security review tractable:
reviewers only need to verify that we call the libraries correctly, not that
we implemented crypto correctly.
Exceptions require explicit authorization in a code comment referencing this
policy.
### Key Decisions ### Key Decisions
- **No framework**: The popup UI is vanilla JS and HTML. The extension is small - **No framework**: The popup UI is vanilla JS and HTML. The extension is small
enough that a framework adds unnecessary complexity and attack surface. enough that a framework adds unnecessary complexity and attack surface.
- **Encrypted storage**: Recovery phrases and private keys are encrypted at rest - **Encrypted storage**: Recovery phrases and private keys are encrypted at rest
in the extension's local storage. The encryption scheme: in the extension's local storage using libsodium. The encryption scheme:
- The user's password is run through PBKDF2-SHA256 (600,000 iterations) with - The user's password is run through Argon2id (`crypto_pwhash`) to derive a
a random salt to derive a 256-bit encryption key. 256-bit encryption key. Argon2id is memory-hard, making GPU/ASIC brute
- The encryption key + a random IV encrypt the secret material using force attacks expensive.
AES-256-GCM. - The derived key encrypts the secret material using XSalsa20-Poly1305
- Stored blob: `{ salt, iv, ciphertext, authTag }`. (`crypto_secretbox`), which provides authenticated encryption (the
ciphertext cannot be tampered with without detection).
- Stored blob: `{ salt, nonce, ciphertext }` (the auth tag is part of the
`crypto_secretbox` output).
- **The password is NOT used in address derivation.** It exists solely to - **The password is NOT used in address derivation.** It exists solely to
protect the recovery phrase / private key on disk. Anyone with the protect the recovery phrase / private key on disk. Anyone with the
recovery phrase can restore the wallet on any device without this recovery phrase can restore the wallet on any device without this
password. This matches MetaMask's behavior. password. This matches MetaMask's behavior.
- **BIP-39 / BIP-44**: Standard mnemonic generation and HD key derivation - **BIP-39 / BIP-44 via ethers.js**: Mnemonic generation, validation, and HD key
(`m/44'/60'/0'/0/n`) for Ethereum address compatibility. The BIP-39 passphrase derivation (`m/44'/60'/0'/0/n`) are handled entirely by ethers.js. The BIP-39
is always empty (matching MetaMask and most wallet software). The user's passphrase is always empty (matching MetaMask and most wallet software). The
password is completely separate and has no effect on which addresses are user's password is completely separate and has no effect on which addresses
generated. are generated.
- **ethers.js for everything Ethereum**: Transaction construction, signing, gas
estimation, RPC communication, ERC-20 contract calls, and address derivation
are all handled by ethers.js. This means zero hand-rolled Ethereum logic.
- **EIP-1193 provider**: The content script injects a `window.ethereum` object - **EIP-1193 provider**: The content script injects a `window.ethereum` object
that implements the EIP-1193 provider interface, enabling web3 site that implements the EIP-1193 provider interface, enabling web3 site
connectivity. connectivity.
- **Minimal RPC**: The extension communicates with Ethereum nodes via JSON-RPC. - **Minimal RPC**: The extension communicates with Ethereum nodes via JSON-RPC
The default endpoint is configurable. No Infura dependency — users can point through ethers.js's `JsonRpcProvider`. The default endpoint is configurable.
it at any Ethereum JSON-RPC endpoint. No Infura dependency — users can point it at any Ethereum JSON-RPC endpoint.
### Supported Functionality ### Supported Functionality

View File

@@ -18,5 +18,8 @@
"prettier": "^3.8.1", "prettier": "^3.8.1",
"tailwindcss": "^4.2.1" "tailwindcss": "^4.2.1"
}, },
"dependencies": {} "dependencies": {
"ethers": "^6.16.0",
"libsodium-wrappers-sumo": "^0.8.2"
}
} }

View File

@@ -2,6 +2,11 @@
# yarn lockfile v1 # yarn lockfile v1
"@adraffy/ens-normalize@1.10.1":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069"
integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.27.1", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0": "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.27.1", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0":
version "7.29.0" version "7.29.0"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c"
@@ -592,6 +597,18 @@
"@emnapi/runtime" "^1.7.1" "@emnapi/runtime" "^1.7.1"
"@tybys/wasm-util" "^0.10.1" "@tybys/wasm-util" "^0.10.1"
"@noble/curves@1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35"
integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==
dependencies:
"@noble/hashes" "1.3.2"
"@noble/hashes@1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==
"@parcel/watcher-android-arm64@2.5.6": "@parcel/watcher-android-arm64@2.5.6":
version "2.5.6" version "2.5.6"
resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz#5f32e0dba356f4ac9a11068d2a5c134ca3ba6564" resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz#5f32e0dba356f4ac9a11068d2a5c134ca3ba6564"
@@ -887,6 +904,13 @@
dependencies: dependencies:
undici-types "~7.18.0" undici-types "~7.18.0"
"@types/node@22.7.5":
version "22.7.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b"
integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==
dependencies:
undici-types "~6.19.2"
"@types/stack-utils@^2.0.3": "@types/stack-utils@^2.0.3":
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
@@ -1006,6 +1030,11 @@
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777"
integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==
aes-js@4.0.0-beta.5:
version "4.0.0-beta.5"
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873"
integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==
ansi-escapes@^4.3.2: ansi-escapes@^4.3.2:
version "4.3.2" version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
@@ -1350,6 +1379,19 @@ esprima@^4.0.0:
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
ethers@^6.16.0:
version "6.16.0"
resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.16.0.tgz#fff9b4f05d7a359c774ad6e91085a800f7fccf65"
integrity sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==
dependencies:
"@adraffy/ens-normalize" "1.10.1"
"@noble/curves" "1.2.0"
"@noble/hashes" "1.3.2"
"@types/node" "22.7.5"
aes-js "4.0.0-beta.5"
tslib "2.7.0"
ws "8.17.1"
execa@^5.1.1: execa@^5.1.1:
version "5.1.1" version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
@@ -2004,6 +2046,18 @@ leven@^3.1.0:
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
libsodium-sumo@^0.8.0:
version "0.8.2"
resolved "https://registry.yarnpkg.com/libsodium-sumo/-/libsodium-sumo-0.8.2.tgz#6aee0ce5d5f850341327a2990531a71319d86c62"
integrity sha512-uMgnjphJ717jLN+jFG1HUgNrK/gOVVfaO1DGZ1Ig/fKLKLVhvaH/sM1I1v784JFvmkJDaczDpi7xSYC4Jvdo1Q==
libsodium-wrappers-sumo@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.8.2.tgz#3bc6ef80070d531622ccd41a317b61d32a78a7f2"
integrity sha512-wd1xAY++Kr6VMikSaa4EPRAHJmFvNlGWiiwU3Jh3GR1zRYF3/I3vy/wYsr4k3LVsNzwb9sqfEQ4LdVQ6zEebyQ==
dependencies:
libsodium-sumo "^0.8.0"
lightningcss-android-arm64@1.31.1: lightningcss-android-arm64@1.31.1:
version "1.31.1" version "1.31.1"
resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz#609ff48332adff452a8157a7c2842fd692a8eac4" resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz#609ff48332adff452a8157a7c2842fd692a8eac4"
@@ -2543,6 +2597,11 @@ to-regex-range@^5.0.1:
dependencies: dependencies:
is-number "^7.0.0" is-number "^7.0.0"
tslib@2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==
tslib@^2.4.0, tslib@^2.8.1: tslib@^2.4.0, tslib@^2.8.1:
version "2.8.1" version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
@@ -2558,6 +2617,11 @@ type-fest@^0.21.3:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
undici-types@~6.19.2:
version "6.19.8"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
undici-types@~7.18.0: undici-types@~7.18.0:
version "7.18.2" version "7.18.2"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.18.2.tgz#29357a89e7b7ca4aef3bf0fd3fd0cd73884229e9" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.18.2.tgz#29357a89e7b7ca4aef3bf0fd3fd0cd73884229e9"
@@ -2661,6 +2725,11 @@ write-file-atomic@^5.0.1:
imurmurhash "^0.1.4" imurmurhash "^0.1.4"
signal-exit "^4.0.1" signal-exit "^4.0.1"
ws@8.17.1:
version "8.17.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b"
integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==
y18n@^5.0.5: y18n@^5.0.5:
version "5.0.8" version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"