0

I'm doing a deep dive into Bitcoin and how it works. I'm currently learning about elliptic curves, signatures and verifications.

I'm reading the steps to for the signature generation algorithm.

It says:

For Alice to sign a message m, she follows these steps:

  1. Calculate e=HASH(m). (Here HASH is a cryptographic hash function, such as SHA-2, with the output converted to an integer.)
  2. Let z be the L_n leftmost bits of e, where L_n is the bit length of the group order n. (Note that z can be greater than n but not longer.)

I don't understand both sentences from 2.

Let's say I have a hash like this:

import { keccakFromString } from 'ethereumjs-util';

// This is Wikipedia's `n`
const BTC_PRIME_MODULO =
  2n ** 256n -
  2n ** 32n -
  2n ** 9n -
  2n ** 8n -
  2n ** 7n -
  2n ** 6n -
  2n ** 4n -
  1n;

const message = 'Learning blockchain development is fun.';
const hash = keccakFromString(message).toString('hex'); // `e` from Wikipedia

const hexToBigInt = (hex: string) => BigInt('0x' + hex);
const bigIntToBinary = (int: bigint) => int.toString(2);

type getFirstNChars = (numberOfChars: number) => (string: string) => string;
const getFirstNChars: getFirstNChars = n => string => string.slice(0, n);
const getFirst256Chars = getFirstNChars(256);
const binaryToBigInt = (binary: string) => BigInt('0b' + binary);

const get256LeftmostBits = pipe(
  hexToBigInt,
  bigIntToBinary,
  getFirst256Chars,
  binaryToBigInt,
);


const z = get256LeftmostBits(hash) // ... Is this correct?

How do I now get z?

Is the group order of Bitcoin FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 and therefore the bit length 256?

And does "z can be greater than n but not longer" mean that z could be BTC_PRIME_MODULO + 1n, so it is greater, but has as many digits? How can z be greater if its the n left most bits?


More context:

I'm trying to implement sign based on that Wikipedia article, and here is what I have so far:

const BITCOIN_GENERATOR_POINT: EllipticCurvePoint = {
  x: 55_066_263_022_277_343_669_578_718_895_168_534_326_250_603_453_777_594_175_500_187_360_389_116_729_240n,
  y: 32_670_510_020_758_816_978_083_085_130_507_043_184_471_273_380_659_243_275_938_904_335_757_337_482_424n,
};

const generateRandomBigInt = () =>
  BigInt(`0x${randomBytes(32).toString('hex')}`);
const getK = pipe(
  generateRandomBigInt,
  maybeReducedModulo(BTC_PRIME_MODULO - 1n),
);

type sign = (privateKey: string, message: string) => string;
const sign: sign = (privateKey, message) => {
  const privateKeyBigInt = BigInt(privateKey);
  const hash = keccakFromString(message).toString('hex');
  let r = 0n;
  let s = 0n;
  const z = get256LeftmostBits(hash); // I'm unsure whether this is correct 

  while (r === 0n || s === 0n) {
    const k = getK();
    const p1 = multiplyWithBasePoint(k);
    r = maybeReduceByBTCPrimeModulo(p1.x);
    s = maybeReduceByBTCPrimeModulo(
      invertByBTCPrimeModulo(k) * (z + r * privateKeyBigInt),
    );
  }

  return ''; // ... need to properly concat r and s ...
};

where

  • maybeReducedModulo given a and b calculates a % b but adds b if a is negative.
  • multiplyWithBasePoint multiplies with the Bitcoin Generator Point G.
  • and invertByBTCPrimeModulo calculates the modular multiplicative inverse with the BTC_PRIME_MODULO.
J. Hesters
  • 13,117
  • 31
  • 133
  • 249
  • In case of curve `secp256k1` which is used in Bitcoin and most cryptocurrencies, bit lengths is 256. Hash length is also 256 (in case of Bitcoin it is double sha256, in case of ethereum it is keccak). You don't need to truncate anything. `z` can be greater than `n`, but chances of this happening are almost negligible. Nothing special will happen with EC crypto in this case. – Zergatul Oct 11 '21 at 15:56
  • @Zergatul That makes sense, wow, thank you! – J. Hesters Oct 11 '21 at 17:23

0 Answers0