emsaPSSVerify function

bool emsaPSSVerify(
  1. List<int> mHash,
  2. List<int> em,
  3. int emBits,
  4. int sLen,
)

Implementation

bool emsaPSSVerify(List<int> mHash, List<int> em, int emBits, int sLen) {
  // See RFC 8017, Section 9.1.2.

  var hLen = 32;

  var emLen = ((emBits + 7) / 8).floor();
  if (emLen != em.length) {
    return false;
  }

  // 1.  If the length of M is greater than the input limitation for the
  //     hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
  //     and stop.
  //
  // 2.  Let mHash = Hash(M), an octet string of length hLen.
  if (hLen != mHash.length) {
    return false;
  }

  // 3.  If emLen < hLen + sLen + 2, output "inconsistent" and stop.
  if (emLen < hLen + sLen + 2) {
    return false;
  }

  // 4.  If the rightmost octet of EM does not have hexadecimal value
  //     0xbc, output "inconsistent" and stop.
  if (em.elementAt(emLen - 1) != 0xbc) {
    return false;
  }

  // 5.  Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
  //     let H be the next hLen octets.
  var db = em.sublist(0, emLen - hLen - 1);
  var h = em.sublist(emLen - hLen - 1, emLen - 1);

  // 6.  If the leftmost 8 * emLen - emBits bits of the leftmost octet in
  //     maskedDB are not all equal to zero, output "inconsistent" and
  //     stop.
  var bitMask = 0xff >> (8 * emLen - emBits);
  if (em[0] & ~bitMask != 0) {
    return false;
  }

  // 7.  Let dbMask = MGF(H, emLen - hLen - 1).
  //
  // 8.  Let DB = maskedDB \xor dbMask.
  mgf1XOR(db, 0, db.length, h, 0, h.length);

  // 9.  Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
  //     to zero.
  db[0] &= bitMask;

  // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
  //     or if the octet at position emLen - hLen - sLen - 1 (the leftmost
  //     position is "position 1") does not have hexadecimal value 0x01,
  //     output "inconsistent" and stop.
  var psLen = emLen - hLen - sLen - 2;
  for (int i = 0; i < psLen; i++) {
    if (db[i] != 0x00) {
      return false;
    }
  }

  if (db[psLen] != 0x01) {
    return false;
  }

  // 11.  Let salt be the last sLen octets of DB.
  var salt = db.sublist(db.length - sLen);

  // 12.  Let
  //          M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;
  //     M' is an octet string of length 8 + hLen + sLen with eight
  //     initial zero octets.
  //
  // 13. Let H' = Hash(M'), an octet string of length hLen.
  List<int> tempList = [];
  tempList.addAll([0, 0, 0, 0, 0, 0, 0, 0]);
  tempList.addAll(mHash);
  tempList.addAll(salt);

  var digest = sha256.convert(tempList);
  var digestBytes = digest.bytes;

  // 14. If H = H', output "consistent." Otherwise, output "inconsistent."
  for (int i = 0; i < digestBytes.length; i++) {
    if (digestBytes[i] != h[i]) {
      return false;
    }
  }

  return true;
}