Skip to content

Instantly share code, notes, and snippets.

@paulmillr
paulmillr / bookmarklet.js
Created March 23, 2025 17:35
download vscode extensions as .vsix
javascript:(function()%7Bconst%20URL_VSIX_PATTERN%20%3D%20'https%3A%2F%2Fmarketplace.visualstudio.com%2F_apis%2Fpublic%2Fgallery%2Fpublishers%2F%24%7Bpublisher%7D%2Fvsextensions%2F%24%7Bextension%7D%2F%24%7Bversion%7D%2Fvspackage'%3B%0A%0Alet%20itemName%20%3D%20new%20URL(window.location.href).searchParams.get('itemName')%3B%0Alet%20%5Bpublisher%2C%20extension%5D%20%3D%20itemName.split('.')%3B%0Alet%20version%20%3D%20document.querySelector('%23versionHistoryTab%20tbody%20tr%20.version-history-container-column').textContent%3B%0A%0Alet%20url%20%3D%20URL_VSIX_PATTERN.replace('%24%7Bpublisher%7D'%2C%20publisher)%0A%09%09%09%09%09%09%20%20.replace('%24%7Bextension%7D'%2C%20extension)%0A%09%09%09%09%09%09%20%20.replace('%24%7Bversion%7D'%2C%20version)%3B%0A%0Awindow.open(url%2C%20'_blank')%3B%7D)()%3B
// PART 1
// secp256k1 curve parameters. Verify using https://www.secg.org/sec2-v2.pdf
const P = 2n ** 256n - 0x1000003d1n; // curve's field prime
const N = 2n ** 256n - 0x14551231950b75fc4402da1732fc9bebfn; // curve (group) order
const CURVE = { P: P, n: N, a: 0n, b: 7n };
const err = (m = ''): never => {
throw new Error(m);
}; // error helper
const M = (a: bigint, b: bigint = P) => {
// mod division
@paulmillr
paulmillr / inp-nacl.mjs
Created April 23, 2024 16:08
noble vs tweetnacl
export { box_keyPair, sign_detached_verify, sign, box, box_open } from 'tweetnacl-ts';
@paulmillr
paulmillr / metamask-sign.md
Last active September 10, 2023 13:36
Tracing cryptography in Metamask dependencies

Tracing cryptography in Metamask dependencies

Metamask uses noble for low-level cryptography operations, such as signature creation. The audit path as per Sep 2023, where every item is name of NPM package:

flowchart TD;
    MM[metamask-extension] -->|imports KeyringController| MMKC["@metamask/keyring-controller"];
    MMKC -->|imports HDKeyring| MMHD["@metamask/eth-hd-keyring"];
 MMKC -->|imports SimpleKeyring| MMSK["@metamask/eth-simple-keyring"];
@paulmillr
paulmillr / noble-vs-elliptic.js
Last active July 26, 2023 08:29
Timing differences between different keys in noble and elliptic
import { secp256k1 } from '@noble/curves/secp256k1';
import elliptic from 'elliptic';
import { mark } from 'micro-bmark';
const EC = elliptic.ec;
(async () => {
var ec = new EC('secp256k1');
const a = '0000000000000000000000000000000000000000000000000000000000000003';
const b = '3000000000000000000000000000000000000000000000000000000000000000';
@paulmillr
paulmillr / hybrid-pkg.md
Last active February 10, 2024 17:45
Why writing hybrid Common.js + ESM NPM packages is hard
  • BigInt literals (15n) are not supported in some environments
    • Must use BigInt('15') instead
    • It was not supported in React Native 0.70. Need to test in new versions
  • Must use hybrid ESM-Common.js package
    • ESM (ECMAScript modules) are not supported in Electron, Jest
      • Electron needs pre-compilation step aka bundler
      • Jest has experimental esm flag, also can be replaced with micro-should
    • Common.js modules (legacy node.js modules) are not supported in browsers, Deno
      • Browsers can be worked around with UMD wrapper
  • Doesn’t play well with ESM in-browser imports
@paulmillr
paulmillr / guide.md
Last active November 4, 2023 15:22
Sign git commits with ssh key

Sign git commits with ssh key

  • git version must be >= 2.34. Earlier versions don't support gpg.format ssh (signing commits with ssh keys).

    If you're printing signature keys in git log by using %GK %GF %GP %GT in git.format.pretty, earlier versions will crash when doing git log with following error:

    BUG: gpg-interface.c:284: bad signature

  • OpenSSH version must be >= 8.8. Earlier versions don't support valid-after,valid-before options.

Fun parts of developing noble-hashes and scure-base

  • Base58 is quadratic (O(n^2)). Basically you can’t encode 1MB of data with it. This has been found with our DoS tests, which we employ for scure-base and noble-hashes. See README for more details
  • Hashes are additionally tested against huge multi-gig inputs, scrypt/pbkdf2 are tested against all possible combination of options. They take 2 hours to run on a decent machine
  • Hashes are actually faster than many wasm alternatives. A single sha256 hashing of 32 bytes of data takes 888 nanoseconds on mac with M1
  • The last fact is extremely remarkable, because we do not employ loop unrolls in the code. A loop unroll is when you’re writing code which could have been executed in loop like for (let step = 0; step < 64), but instead, you’re writing every iteration step-by-step. Which incr
@paulmillr
paulmillr / unrolled-noble-sha3.ts
Last active September 2, 2022 11:32
Replace sha3.js in node_modules/@noble/hashes with unrolled-sha3.js
const rotlHs = (h: string, l: string, s: number) =>
s > 32 ? `(${l} << ${s - 32}) | (${h} >>> ${64 - s})` : `(${h} << ${s}) | (${l} >>> ${32 - s})`;
const rotlLs = (h: string, l: string, s: number) =>
s > 32 ? `(${h} << ${s - 32}) | (${l} >>> ${64 - s})` : `(${l} << ${s}) | (${h} >>> ${32 - s})`;
export const keccakP = (() => {
let out = 'let h, l, s = state;\n';
const vars = [];
for (let i = 0; i < 200 / 4; i++) vars.push(`s${i} = s[${i}]`);
out += `let ${vars.join(', ')};\n`;
@paulmillr
paulmillr / pgp_proof.txt
Last active July 2, 2022 22:49
PGP verification
Proving ownership of
- paulmillr.com/pgp_proof.txt via paulmillr.com/pgp_proof.txt.asc
- twitter.com/paulmillr
- github.com/paulmillr via gist.github.com/paulmillr/cb3ad3b9cd4ac849eb1def3634f93421
- Active key: Paul Miller (PGP 697079DA6878B89B) from 3 Jul 2022
- Revoked key: Paul Miller (PGP 46BEEF337A641ABB) was active from 15 Apr 2020 to 2 Jul 2022
Full pubkey: