extractPublicKey method

Future<Uint8List> extractPublicKey(
  1. Uint8List message,
  2. Uint8List sig
)

Implementation

Future<Uint8List> extractPublicKey(Uint8List message, Uint8List sig) async {
  if ((sig.length != SignatureSize) || (sig[63] & 224 != 0)) {
    throw ("bad signature format");
  }

  var h = Sha512().newHashSink();

  h.add(sig.sublist(0, 32));
  h.add(message);
  h.close();

  var hash = await h.hash();

  Uint8List digest = Uint8List.fromList(hash.bytes);

  Uint8List hReduced = Uint8List(32);
  ScReduce(hReduced, digest);

  Uint8List hInv = Uint8List(32);
  hInv = InvertModL(hReduced);

  Uint8List s = sig.sublist(32);

  if (s.length != PublicKeySize) {
    throw ("memory copy failed");
  }

  if (!ScMinimal(s)) throw ("invalid sig");

  Uint8List one = new Uint8List(32);
  one[0] = 1;

  ExtendedGroupElement R = new ExtendedGroupElement();
  Uint8List r = sig.sublist(0, 32);
  if (!R.FromBytes(r))
    throw ("failed to create extended group element from s");

  FeNeg(R.X, R.X);
  FeNeg(R.T, R.T);

  ProjectiveGroupElement A = new ProjectiveGroupElement();
  ExtendedGroupElement A2 = new ExtendedGroupElement();
  GeDoubleScalarMultVartime(A, one, R, s);
  A.ToExtended(A2);

  ProjectiveGroupElement ecpk = new ProjectiveGroupElement();
  GeScalarMultVartime(ecpk, hInv, A2);

  Uint8List pubkey = new Uint8List(PublicKeySize);
  ecpk.ToBytes(pubkey);

  return pubkey;
}