ECDSA для значений биткойнов: что такое z?

#typescript #digital-signature #bitcoin #modulo #ecdsa

Вопрос:

Я глубоко погружаюсь в биткойн и то, как он работает. В настоящее время я изучаю эллиптические кривые, подписи и проверки.

Я читаю инструкции по алгоритму генерации подписи.

В нем говорится::

Чтобы Алиса подписала сообщение m , она выполняет следующие действия:

  1. Вычислять e=HASH(m) . (Здесь ХЭШ-это криптографическая хэш-функция, такая как SHA-2, с выводом, преобразованным в целое число.)
  2. Пусть z будут L_n крайние левые биты e , где L_n -длина бита группового порядка n . (Обратите внимание, что это z может быть больше n , но не больше.)

Я не понимаю обоих предложений из 2.

Допустим, у меня есть hash такой:

 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?
 

Как мне теперь добраться z ?

Является ли групповой порядок биткоина FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 и, следовательно, длина бита 256?

И означает ли « z может быть больше n , но не длиннее», что это z может быть BTC_PRIME_MODULO 1n , поэтому оно больше, но имеет столько же цифр? Как может z быть больше, если его n осталось больше всего битов?


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 ...
};
 

где

  • maybeReducedModulo дано a и b вычисляет a % b , но добавляет b , если a отрицательно.
  • multiplyWithBasePoint умножается с помощью точки генератора Биткойнов G .
  • и invertByBTCPrimeModulo вычисляет модульную мультипликативную обратную величину с BTC_PRIME_MODULO помощью .

Комментарии:

1. В случае кривой secp256k1 , которая используется в биткойне и большинстве криптовалют, длина бита равна 256. Длина хэша также равна 256 (в случае биткоина это двойной sha256, в случае эфириума-keccak). Вам не нужно ничего урезать. z может быть больше , чем n , но вероятность того, что это произойдет, почти ничтожна. В этом случае с EC crypto не произойдет ничего особенного.

2. @Zergatul В этом есть смысл, вау, спасибо!