setWideBytes method

void setWideBytes(
  1. Uint8List x
)

This file contains additional functionality that is not included in the upstream crypto/ed25519/edwards25519/field package.

SetWideBytes sets v to x, where x is a 64-byte little-endian encoding, which is reduced modulo the field order. If x is not of the right length, SetWideBytes returns nil and an error, and the receiver is unchanged.

SetWideBytes is not necessary to select a uniformly distributed value, and is only provided for compatibility: SetBytes can be used instead as the chance of bias is less than 2⁻²⁵⁰.

Implementation

void setWideBytes(Uint8List x) {
  if (x.length != 64) {
    throw ArgumentError('edwards25519: invalid SetWideBytes input size');
  }

  // Split the 64 bytes into two elements, and extract the most significant
  // bit of each, which is ignored by SetBytes.
  final lo = Element.feZero()..setBytes(x.sublist(0, 32));
  final loMSB = (x[31] >> 7).toBigInt;
  final hi = Element.feZero()..setBytes(x.sublist(32));
  final hiMSB = (x[63] >> 7).toBigInt;

  // The output we want is
  //
  //   v = lo + loMSB * 2²⁵⁵ + hi * 2²⁵⁶ + hiMSB * 2⁵¹¹
  //
  // which applying the reduction identity comes out to
  //
  //   v = lo + loMSB * 19 + hi * 2 * 19 + hiMSB * 2 * 19²
  //
  // l0 will be the sum of a 52 bits value (lo.l0), plus a 5 bits value
  // (loMSB * 19), a 6 bits value (hi.l0 * 2 * 19), and a 10 bits value
  // (hiMSB * 2 * 19²), so it fits in a uint64.

  l0 = lo.l0 +
      (loMSB * bigInt19) +
      (hi.l0 * BigInt.two * bigInt19) +
      (hiMSB * BigInt.two * bigInt19 * bigInt19);
  l1 = lo.l1 + (hi.l1 * BigInt.two * bigInt19);
  l2 = lo.l2 + (hi.l2 * BigInt.two * bigInt19);
  l3 = lo.l3 + (hi.l3 * BigInt.two * bigInt19);
  l4 = lo.l4 + (hi.l4 * BigInt.two * bigInt19);
  carryPropagateGeneric();
}