def props(b: bytes, i: int): ''' ``props`` is a little-endian 64 bit value that represents informal properties about the resolver. It is a logical OR combination of the following values: - ``1``: the server supports DNSSEC - ``2``: the server doesn’t keep logs - ``4``: the server doesn’t intentionally block domains For example, a server that supports DNSSEC, stores logs, but doesn’t block anything on its own should set ``props`` as the following 8 bytes sequence: ``[ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]``. ''' props = b[i] dnssec = not not ((props >> 0) & 1) nolog = not not ((props >> 1) & 1) nofilter = not not ((props >> 2) & 1) i = i + 8 return i, dnssec, nolog, nofilter def LP(b: bytes, i: int): ''' ``a || b`` is the concatenation of ``a`` and ``b`` ``len(x)`` is a single byte representation of the length of ``x``, in bytes. Strings don’t have to be zero-terminated and do not require invidual encoding. ``LP(x)`` is ``len(x) || x``, i.e ``x`` prefixed by its length. ''' x_len = b[i] i = i + 1 x = b[i:i + x_len] i = i + x_len return i, x def LP_decode(b: bytes, i: int, encoding='utf-8'): i, x = LP(b, i) return i, x.decode(encoding) def LP_pk(b: bytes, i: int): i, x = LP(b, i) if len(x) != 32: raise ValueError("LP(pk)") hpk = x.hex().upper() hpks = [] for j in range(0, 16): hpks.append(hpk[j * 4: j * 4 + 4]) pk = ":".join(hpks) return i, pk def VLP(b: bytes, i: int): ''' ``a | b`` is the result of the logical ``OR`` operation between ``a`` and ``b``. ``vlen(x)`` is equal to ``len(x)`` if ``x`` is the last element of a set, and ``0x80 | len(x)`` if there are more elements in the set. ``VLP(x1, x2, ...xn)`` encodes a set, as ``vlen(x1) || x1 || vlen(x2) || x2 ... || vlen(xn) || xn``. Since ``vlen(xn) == len(xn)`` (length of the last element doesn’t have the high bit set), for a set with a single element, we have ``VLP(x) == LP(x)``. ''' xx = [] last_element = False while True: if b[i] & 0x80 == 0: last_element = True x_len = b[i] else: x_len = b[i] ^ 0x80 i = i + 1 if x_len > 0: x = b[i:i + x_len] xx.append(x) i = i + x_len if last_element: return i, xx def VLP_hashs(b: bytes, i: int): i, xx = VLP(b, i) hashs = list(map(lambda x: x.hex(), xx)) return i, hashs def VLP_bootstrap_ipi(b: bytes, i: int): i, xx = VLP(b, i) bootstrap_ipi = list(map(lambda x: x.decode("utf-8"), xx)) return i, bootstrap_ipi