Skip to content

Instantly share code, notes, and snippets.

View micro-rlp.ts
import * as P from 'micro-packed';
export type Input = string | number | Uint8Array | bigint | List | null;
export type List = Input[];
// length: first 3 bit !== 111 ? 6 bit length : 3bit lenlen
const rlpLen = () =>
encodeStream(w: P.Writer, value: number) {
if (value < 56) return w.bits(value, 6);
w.bits(0b111, 3);
paulmillr /
Last active May 30, 2022
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 &lt; 64), but instead, you’re writing every iteration step-by-step. Which incr
View unrolled-noble-sha3.ts
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 /
Last active Jul 22, 2022
elliptic.js compatibility layer on top of noble-secp256k1

elliptic.js compatibility layer on top of noble-secp256k1

Update 22 Jul 2022: We have the actual code here

Stuff below was just initial thoughts.

There are two issues:

  1. Elliptic has dumb validation logic. E.g. it throws if signature.r >= CURVE.order; but not if signature.r == 0. Noble throws for all invalid values of r/s. Noble verify() doesn't throw if message length is not 32-byte, elliptic throws.
  2. Different signature format: noble outputs der-encoded ecdsa signatures. elliptic.js uses different signature format called Compact. It outputs 64 bytes (32 bytes r, 32 bytes s).
View bls12-frob.nim
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at
# * Apache v2 license (license terms in the root directory or at
# at your option. This file may not be copied, modified, or distributed except according to those terms.
#! /usr/bin/env python3
# This file is dual-licensed. Choose whichever licence you want from
# the two licences listed below.
# The first licence is a regular 2-clause BSD licence. The second licence
# is the CC-0 from Creative Commons. It is intended to release Monocypher
# to the public domain. The BSD licence serves as a fallback option.
# SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
paulmillr / ed25519-bug.js
Created May 30, 2020
Torsion safe representatives in ed25519
View ed25519-bug.js
const ed = require('noble-ed25519');
const D = ed.Point.fromHex(ed.utils.TORSION_SUBGROUP[3]) // 26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05
// Point {
// x: 14399317868200118260347934320527232580618823971194345261214217575416788799818n,
// y: 2707385501144840649318225287225658788936804267575313519463743609750303402022n
const privateKey = '01020304050607080910111213141516';
const P = ed.Point.BASE.multiply(BigInt('0x'+privateKey))
// Point {
// x: 759756512641423873946439870058443608688414856670287422413795292548523931103n,
paulmillr / pgp_proof.txt
Last active Jul 2, 2022
PGP verification
View pgp_proof.txt
Proving ownership of
- via
- via
- 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:

Hal Finney's explanation of secp256k1 "efficiently computable endomorphism" parameters used secp256k1 libraries, archived from source.

The same optimization could be applied to any Koblitz curve (e.g. Short Weistrass curve with a=0).

I implemented an optimized ECDSA verify for the secp256k1 curve, based on pages 125-129 of the Guide to Elliptic Curve Cryptography, by Hankerson, Menezes and Vanstone. I own the book but I also found a PDF on a Russian site which is more convenient.

secp256k1 uses the following prime for its x and y coordinates: