private int getPwned(byte[] hash, bool needCount) { if (hash == null) { throw new ArgumentNullException("hash"); } if (hash.Length != 20) { throw new ArgumentException("The hash is expected to be 20 bytes long.", "hash"); } if (_stream == null || _reader == null) { throw new ObjectDisposedException(nameof(PwnedChecker)); } int prefix = (hash[0] << 16) + (hash[1] << 8) + hash[2]; _stream.Position = prefix * 5; long pos = _reader.ReadUInt32(); pos += (long)_reader.ReadByte() << 32; if (pos == 0) { return(0); } _stream.Position = pos; int entryCount = _reader.Read7BitEncodedInt(); if (entryCount == 0) { return(0); } var bytes = _reader.ReadBytes(entryCount * 17); int min = 0; int max = entryCount - 1; int cur = 0; while (true) { cur = (min + max) / 2; for (int i = 0; i < 17; i++) { int cmp = hash[3 + i] - bytes[cur * 17 + i]; if (cmp < 0) { max = cur - 1; goto different; } else if (cmp > 0) { min = cur + 1; goto different; } } break; // match found; its index is in "cur" different: if (min > max) { return(0); } } if (!needCount) { return(1); } for (int i = 0; i < cur; i++) { _reader.Read7BitEncodedInt(); } return(_reader.Read7BitEncodedInt()); }