feTobytes static method

void feTobytes(
  1. List<int> s,
  2. FieldElement h
)

Implementation

static void feTobytes(List<int> s, FieldElement h) {
  s.asMin32("feTobytes");
  BigInt h0 = h.h[0].toBig;
  BigInt h1 = h.h[1].toBig;
  BigInt h2 = h.h[2].toBig;
  BigInt h3 = h.h[3].toBig;
  BigInt h4 = h.h[4].toBig;
  BigInt h5 = h.h[5].toBig;
  BigInt h6 = h.h[6].toBig;
  BigInt h7 = h.h[7].toBig;
  BigInt h8 = h.h[8].toBig;
  BigInt h9 = h.h[9].toBig;
  BigInt q;
  BigInt carry0;
  BigInt carry1;
  BigInt carry2;
  BigInt carry3;
  BigInt carry4;
  BigInt carry5;
  BigInt carry6;
  BigInt carry7;
  BigInt carry8;
  BigInt carry9;

  q = (BigInt.from(19) * h9 + ((1) << 24).toBig) >> 25;
  q = (h0 + q) >> 26;
  q = (h1 + q) >> 25;
  q = (h2 + q) >> 26;
  q = (h3 + q) >> 25;
  q = (h4 + q) >> 26;
  q = (h5 + q) >> 25;
  q = (h6 + q) >> 26;
  q = (h7 + q) >> 25;
  q = (h8 + q) >> 26;
  q = (h9 + q) >> 25;
  /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
  h0 += BigInt.from(19) * q;
  /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */

  carry0 = (h0 >> 26);
  h1 += carry0;
  h0 -= carry0 << 26;
  carry1 = h1 >> 25;
  h2 += carry1;
  h1 -= carry1 << 25;
  carry2 = h2 >> 26;
  h3 += carry2;
  h2 -= carry2 << 26;
  carry3 = h3 >> 25;
  h4 += carry3;
  h3 -= carry3 << 25;
  carry4 = h4 >> 26;
  h5 += carry4;
  h4 -= carry4 << 26;
  carry5 = h5 >> 25;
  h6 += carry5;
  h5 -= carry5 << 25;
  carry6 = h6 >> 26;
  h7 += carry6;
  h6 -= carry6 << 26;
  carry7 = h7 >> 25;
  h8 += carry7;
  h7 -= carry7 << 25;
  carry8 = h8 >> 26;
  h9 += carry8;
  h8 -= carry8 << 26;
  carry9 = h9 >> 25;
  h9 -= carry9 << 25;
  /* h10 = carry9 */

  /*
Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
Have h0+...+2^230 h9 between 0 and 2^255-1;
evidently 2^255 h10-2^255 q = 0.
Goal: Output h0+...+2^230 h9.
*/
  List<BigInt> sBig = List<BigInt>.filled(32, BigInt.zero);
  sBig[0] = h0 >> 0;
  sBig[1] = h0 >> 8;
  sBig[2] = h0 >> 16;
  sBig[3] = (h0 >> 24) | (h1 << 2);
  sBig[4] = h1 >> 6;
  sBig[5] = h1 >> 14;
  sBig[6] = (h1 >> 22) | (h2 << 3);
  sBig[7] = h2 >> 5;
  sBig[8] = h2 >> 13;
  sBig[9] = (h2 >> 21) | (h3 << 5);
  sBig[10] = h3 >> 3;
  sBig[11] = h3 >> 11;
  sBig[12] = (h3 >> 19) | (h4 << 6);
  sBig[13] = h4 >> 2;
  sBig[14] = h4 >> 10;
  sBig[15] = h4 >> 18;
  sBig[16] = h5 >> 0;
  sBig[17] = h5 >> 8;
  sBig[18] = h5 >> 16;
  sBig[19] = (h5 >> 24) | (h6 << 1);
  sBig[20] = h6 >> 7;
  sBig[21] = h6 >> 15;
  sBig[22] = (h6 >> 23) | (h7 << 3);
  sBig[23] = h7 >> 5;
  sBig[24] = h7 >> 13;
  sBig[25] = (h7 >> 21) | (h8 << 4);
  sBig[26] = h8 >> 4;
  sBig[27] = h8 >> 12;
  sBig[28] = (h8 >> 20) | (h9 << 6);
  sBig[29] = h9 >> 2;
  sBig[30] = h9 >> 10;
  sBig[31] = h9 >> 18;
  for (int i = 0; i < s.length; i++) {
    s[i] = sBig[i].toUnsigned8;
  }
}