Build hashes and recovery-phrase entropy come from ethers (closes #758) #767

Open
clawbot wants to merge 1 commits from issue-758-crypto-through-ethers into next
pull from: issue-758-crypto-through-ethers
5 changed files with 27 additions and 18 deletions

No files matched your search

+4 -5
View File
@@ -1647,11 +1647,10 @@ The development dependencies ship nowhere:
### Crypto policy
Hashing, key derivation, signing and encryption go through `ethers` or
`libsodium-wrappers-sumo`. No primitive is implemented in this repository. A new
recovery phrase draws its random bytes from the browser's
`crypto.getRandomValues()`. The build tooling, `build.js` and `script/lib/`,
hashes files with Node's `crypto`; none of it ships in the extension.
In the extension, hashing, key derivation, signing and encryption go through
`ethers` or `libsodium-wrappers-sumo`. A new recovery phrase takes its random
bytes from `ethers`. `build.js` and `script/lib/package.js` also hash files with
`ethers`. No primitive is implemented in this repository.
### Content Security Policy
+3 -5
View File
@@ -1,8 +1,8 @@
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const { execSync } = require("child_process");
const esbuild = require("esbuild");
const { sha256 } = require("ethers");
const { resolveVersion } = require("./script/lib/version");
const {
BACKGROUND_ENTRY_PREFIX,
@@ -314,10 +314,8 @@ function copyIcons(distDir) {
}
function sha256File(absPath) {
return crypto
.createHash("sha256")
.update(fs.readFileSync(absPath))
.digest("hex");
// ethers prefixes the hex with 0x; the receipt holds bare hex.
return sha256(fs.readFileSync(absPath)).slice(2);
}
// Write the receipt for the files this build emitted. Deliberately records no
+9 -3
View File
@@ -25,9 +25,9 @@
"use strict";
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const ethers = require("ethers");
const { readZip, writeZip } = require("./zip");
const { resolveVersion } = require("./version");
@@ -60,8 +60,9 @@ function fail(message) {
throw new Error(message);
}
// Lowercase hex without the 0x prefix ethers adds, as sha256sum prints it.
function sha256(buf) {
return crypto.createHash("sha256").update(buf).digest("hex");
return ethers.sha256(buf).slice(2);
}
// Every regular file under dir, as archive-root-relative forward-slashed
@@ -291,4 +292,9 @@ if (require.main === module) {
}
}
module.exports = { checkSelfContained, htmlReferences, manifestReferences };
module.exports = {
checkSelfContained,
htmlReferences,
manifestReferences,
sha256,
};
+2 -5
View File
@@ -1,7 +1,7 @@
// Wallet operations: mnemonic generation, HD derivation, signing.
// All crypto delegated to ethers.js.
const { Mnemonic, HDNodeWallet, Wallet } = require("ethers");
const { Mnemonic, HDNodeWallet, Wallet, randomBytes } = require("ethers");
const { DEBUG, DEBUG_MNEMONIC, BIP44_ETH_PATH } = require("./constants");
function generateMnemonic() {
@@ -10,10 +10,7 @@ function generateMnemonic() {
// settings toggle drives, which would let a user of a release build turn
// the hardcoded, publicly known test phrase back on for real wallets.
if (DEBUG) return DEBUG_MNEMONIC;
const m = Mnemonic.fromEntropy(
globalThis.crypto.getRandomValues(new Uint8Array(16)),
);
return m.phrase;
return Mnemonic.fromEntropy(randomBytes(16)).phrase;
}
// Every extended key (xprv or xpub) entering the app goes through this.
+9
View File
@@ -17,6 +17,7 @@ const {
checkSelfContained,
htmlReferences,
manifestReferences,
sha256,
} = require("../script/lib/package");
const { readZip, writeZip } = require("../script/lib/zip");
@@ -142,6 +143,14 @@ describe("archive self-containment", () => {
});
});
// release/SHA256SUMS is checked with `sha256sum -c`, which needs the digest
// as bare lowercase hex. The expected value is the FIPS 180-2 digest of "abc".
test("sha256 prints the digest as sha256sum does", () => {
expect(sha256(Buffer.from("abc"))).toBe(
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
);
});
describe("the zip container", () => {
const files = [
{ name: "manifest.json", data: Buffer.from('{"a":1}') },