def spx_verify(self, m, sig, public_key): adrs = ADRS() r = sig[0] sig_fors = sig[1] sig_ht = sig[2] public_seed = public_key[0] public_root = public_key[1] size_md = math.floor((self._k * self._a + 7) / 8) size_idx_tree = math.floor((self._h - self._h // self._d + 7) / 8) size_idx_leaf = math.floor((self._h // self._d + 7) / 8) digest = hash_msg(r, public_seed, public_root, m, size_md + size_idx_tree + size_idx_leaf) tmp_md = digest[:size_md] tmp_idx_tree = digest[size_md:(size_md + size_idx_tree)] tmp_idx_leaf = digest[(size_md + size_idx_tree):len(digest)] md_int = int.from_bytes(tmp_md, 'big') >> (len(tmp_md) * 8 - self._k * self._a) md = md_int.to_bytes(math.ceil(self._k * self._a / 8), 'big') idx_tree = int.from_bytes(tmp_idx_tree, 'big') >> (len(tmp_idx_tree) * 8 - (self._h - self._h // self._d)) idx_leaf = int.from_bytes(tmp_idx_leaf, 'big') >> (len(tmp_idx_leaf) * 8 - (self._h // self._d)) adrs.set_layer_address(0) adrs.set_tree_address(idx_tree) adrs.set_type(ADRS.FORS_TREE) adrs.set_key_pair_address(idx_leaf) pk_fors = self.fors_pk_from_sig(sig_fors, md, public_seed, adrs) adrs.set_type(ADRS.TREE) return self.ht_verify(pk_fors, sig_ht, public_seed, idx_tree, idx_leaf, public_root)
def ht_verify(self, m, sig_ht, public_seed, idx_tree, idx_leaf, public_key_ht): adrs = ADRS() sigs_xmss = self.sigs_xmss_from_sig_ht(sig_ht) sig_tmp = sigs_xmss[0] adrs.set_layer_address(0) adrs.set_tree_address(idx_tree) node = self.xmss_pk_from_sig(idx_leaf, sig_tmp, m, public_seed, adrs) for j in range(1, self._d): idx_leaf = idx_tree % 2 ** self._h_prime idx_tree = idx_tree >> self._h_prime sig_tmp = sigs_xmss[j] adrs.set_layer_address(j) adrs.set_tree_address(idx_tree) node = self.xmss_pk_from_sig(idx_leaf, sig_tmp, node, public_seed, adrs) if node == public_key_ht: return True else: return False
def ht_sign(self, m, secret_seed, public_seed, idx_tree, idx_leaf): adrs = ADRS() adrs.set_layer_address(0) adrs.set_tree_address(idx_tree) sig_tmp = self.xmss_sign(m, secret_seed, idx_leaf, public_seed, adrs.copy()) sig_ht = sig_tmp root = self.xmss_pk_from_sig(idx_leaf, sig_tmp, m, public_seed, adrs.copy()) for j in range(1, self._d): idx_leaf = idx_tree % 2**self._h_prime idx_tree = idx_tree >> self._h_prime adrs.set_layer_address(j) adrs.set_tree_address(idx_tree) sig_tmp = self.xmss_sign(root, secret_seed, idx_leaf, public_seed, adrs.copy()) sig_ht = sig_ht + sig_tmp if j < self._d - 1: root = self.xmss_pk_from_sig(idx_leaf, sig_tmp, root, public_seed, adrs.copy()) return sig_ht
def spx_sign(self, m, secret_key): adrs = ADRS() secret_seed = secret_key[0] secret_prf = secret_key[1] public_seed = secret_key[2] public_root = secret_key[3] opt = bytes(self._n) if self._randomize: opt = os.urandom(self._n) r = prf_msg(secret_prf, opt, m, self._n) sig = [r] size_md = math.floor((self._k * self._a + 7) / 8) size_idx_tree = math.floor((self._h - self._h // self._d + 7) / 8) size_idx_leaf = math.floor((self._h // self._d + 7) / 8) digest = hash_msg(r, public_seed, public_root, m, size_md + size_idx_tree + size_idx_leaf) tmp_md = digest[:size_md] tmp_idx_tree = digest[size_md:(size_md + size_idx_tree)] tmp_idx_leaf = digest[(size_md + size_idx_tree):len(digest)] md_int = int.from_bytes(tmp_md, 'big') >> (len(tmp_md) * 8 - self._k * self._a) md = md_int.to_bytes(math.ceil(self._k * self._a / 8), 'big') idx_tree = int.from_bytes(tmp_idx_tree, 'big') >> (len(tmp_idx_tree) * 8 - (self._h - self._h // self._d)) idx_leaf = int.from_bytes(tmp_idx_leaf, 'big') >> (len(tmp_idx_leaf) * 8 - (self._h // self._d)) adrs.set_layer_address(0) adrs.set_tree_address(idx_tree) adrs.set_type(ADRS.FORS_TREE) adrs.set_key_pair_address(idx_leaf) sig_fors = self.fors_sign(md, secret_seed, public_seed, adrs.copy()) sig += [sig_fors] pk_fors = self.fors_pk_from_sig(sig_fors, md, public_seed, adrs.copy()) adrs.set_type(ADRS.TREE) sig_ht = self.ht_sign(pk_fors, secret_seed, public_seed, idx_tree, idx_leaf) sig += [sig_ht] return sig
def ht_pk_gen(self, secret_seed, public_seed): adrs = ADRS() adrs.set_layer_address(self._d - 1) adrs.set_tree_address(0) root = self.xmss_pk_gen(secret_seed, public_seed, adrs.copy()) return root