예제 #1
0
    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
예제 #2
0
    def treehash(self, secret_seed, s, z, public_seed, adrs: ADRS):
        if s % (1 << z) != 0:
            return -1

        stack = []

        for i in range(0, 2 ** z):
            adrs.set_type(ADRS.WOTS_HASH)
            adrs.set_key_pair_address(s + i)
            node = self.wots_pk_gen(secret_seed, public_seed, adrs.copy())

            adrs.set_type(ADRS.TREE)
            adrs.set_tree_height(1)
            adrs.set_tree_index(s + i)

            if len(stack) > 0:
                while stack[len(stack) - 1]['height'] == adrs.get_tree_height():
                    adrs.set_tree_index((adrs.get_tree_index() - 1) // 2)
                    node = hash(public_seed, adrs.copy(), stack.pop()['node'] + node, self._n)
                    adrs.set_tree_height(adrs.get_tree_height() + 1)

                    if len(stack) <= 0:
                        break

            stack.append({'node': node, 'height': adrs.get_tree_height()})

        return stack.pop()['node']
예제 #3
0
    def wots_pk_from_sig(self, sig, m, public_seed, adrs: ADRS):
        csum = 0
        wots_pk_adrs = adrs.copy()

        msg = base_w(m, self._w, self._len_1)

        for i in range(0, self._len_1):
            csum += self._w - 1 - msg[i]

        padding = (self._len_2 * math.floor(math.log(self._w, 2))) % 8 if (
            self._len_2 * math.floor(math.log(self._w, 2))) % 8 != 0 else 8
        csum = csum << (8 - padding)
        csumb = csum.to_bytes(math.ceil(
            (self._len_2 * math.floor(math.log(self._w, 2))) / 8),
                              byteorder='big')
        csumw = base_w(csumb, self._w, self._len_2)
        msg += csumw

        tmp = bytes()
        for i in range(0, self._len_0):
            adrs.set_chain_address(i)
            tmp += self.chain(sig[i], msg[i], self._w - 1 - msg[i],
                              public_seed, adrs.copy())

        wots_pk_adrs.set_type(ADRS.WOTS_PK)
        wots_pk_adrs.set_key_pair_address(adrs.get_key_pair_address())
        pk_sig = hash(public_seed, wots_pk_adrs, tmp, self._n)
        return pk_sig
예제 #4
0
    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
예제 #5
0
    def wots_pk_gen(self, secret_seed, public_seed, adrs: ADRS):
        wots_pk_adrs = adrs.copy()
        tmp = bytes()
        for i in range(0, self._len_0):
            adrs.set_chain_address(i)
            adrs.set_hash_address(0)
            sk = prf(secret_seed, adrs.copy(), self._n)
            tmp += bytes(self.chain(sk, 0, self._w - 1, public_seed, adrs.copy()))

        wots_pk_adrs.set_type(ADRS.WOTS_PK)
        wots_pk_adrs.set_key_pair_address(adrs.get_key_pair_address())

        pk = hash(public_seed, wots_pk_adrs, tmp, self._n)
        return pk
예제 #6
0
 def wots_sk_gen(self, secret_seed, adrs: ADRS):  # Not necessary
     sk = []
     for i in range(0, self._len_0):
         adrs.set_chain_address(i)
         adrs.set_hash_address(0)
         sk.append(prf(secret_seed, adrs.copy(), self._n))
     return sk
예제 #7
0
    def fors_pk_gen(self, secret_seed, public_seed, adrs: ADRS):
        fors_pk_adrs = adrs.copy()

        root = bytes()
        for i in range(0, self._k):
            root += self.fors_treehash(secret_seed, i * self._t, self._a, public_seed, adrs)

        fors_pk_adrs.set_type(ADRS.FORS_ROOTS)
        fors_pk_adrs.set_key_pair_address(adrs.get_key_pair_address())
        pk = hash(public_seed, fors_pk_adrs, root, self._n)
        return pk
예제 #8
0
    def fors_pk_from_sig(self, sig_fors, m, public_seed, adrs: ADRS):
        m_int = int.from_bytes(m, 'big')

        sigs = self.auths_from_sig_fors(sig_fors)
        root = bytes()

        for i in range(0, self._k):
            idx = (m_int >> (self._k - 1 - i) * self._a) % self._t

            sk = sigs[i][0]
            adrs.set_tree_height(0)
            adrs.set_tree_index(i * self._t + idx)
            node_0 = hash(public_seed, adrs.copy(), sk, self._n)
            node_1 = 0

            auth = sigs[i][1]
            adrs.set_tree_index(i * self._t + idx)  # Really Useful?

            for j in range(0, self._a):
                adrs.set_tree_height(j + 1)

                if math.floor(idx / 2**j) % 2 == 0:
                    adrs.set_tree_index(adrs.get_tree_index() // 2)
                    node_1 = hash(public_seed, adrs.copy(), node_0 + auth[j],
                                  self._n)
                else:
                    adrs.set_tree_index((adrs.get_tree_index() - 1) // 2)
                    node_1 = hash(public_seed, adrs.copy(), auth[j] + node_0,
                                  self._n)

                node_0 = node_1

            root += node_0

        fors_pk_adrs = adrs.copy()
        fors_pk_adrs.set_type(ADRS.FORS_ROOTS)
        fors_pk_adrs.set_key_pair_address(adrs.get_key_pair_address())

        pk = hash(public_seed, fors_pk_adrs, root, self._n)
        return pk
예제 #9
0
    def fors_sk_gen(self, secret_seed, adrs: ADRS, idx):
        adrs.set_tree_height(0)
        adrs.set_tree_index(idx)
        sk = prf(secret_seed, adrs.copy(), self._n)

        return sk
예제 #10
0
 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
예제 #11
0
 def xmss_pk_gen(self, secret_seed, public_key, adrs: ADRS):
     pk = self.treehash(secret_seed, 0, self._h_prime, public_key, adrs.copy())
     return pk