def pseudo_share_participant(self, i_secret, q_group, participant):
        """ pseudo share generation for a single participant
            U = h(x || i_U || q_v)
        """
        print('Pseudo share computation for secret s%r, access group A%r,'
              'participant P%r' % (i_secret, q_group, participant))

        # l = length of longest access group for this secret
        lengths = []
        gamma = self.access_structures[i_secret]
        for A in gamma:
            lengths.append(len(A)-1)
        l = max(lengths)
        u = floor(log2(self.k)) + 1 # u = bit length of number of secrets k
        v = floor(log2(l)) + 1  # v = bit length of l
        
        # concatenate x, i and q binary
        if isinstance(self.master_shares_x[participant-1], bytes):
            bytes_x = self.master_shares_x[participant-1]
        else:
            bytes_x = bytes([ self.master_shares_x[participant-1] ])
        bytes_i = bytes([i_secret])
        bytes_q = bytes([q_group])

        message = b''.join([bytes_x, bytes_i, bytes_q])  # python 3.x
        # hash the concatenated bytes
        hash_of_message = common.hash(message, self.hash_len, self.hash_aes_nonce)
        share = common.modulo_p(self.p, hash_of_message)
        #print('Pseudo share for secret s%d, access group A%d, participant P%d:\nU = ' % (i_secret, q_group, participant), share.hex())
        return share
Esempio n. 2
0
    def pseudo_share_participant(self, i_secret, q_group, participant):
        """ pseudo share generation for a single participant
            U = hash(master_share_x) XOR master_share_x
        """
        print('Pseudo share computation for secret s%r, access group A%r,'
              'participant P%r' % (i_secret, q_group, participant))

        # convert master share to bytes
        if isinstance(self.master_shares_x[participant - 1], bytes):
            bytes_x = self.master_shares_x[participant - 1]
            int_x = int.from_bytes(self.master_shares_x[participant - 1],
                                   byteorder='big')
        else:
            bytes_x = bytes([self.master_shares_x[participant - 1]])
            int_x = self.master_shares_x[participant - 1]

        # hash the master share
        hash_of_master_share = common.hash(bytes_x, self.hash_len,
                                           self.hash_aes_nonce)
        hash_of_master_share = common.modulo_p(self.p, hash_of_master_share)

        hash_of_master_share_int = int.from_bytes(hash_of_master_share,
                                                  byteorder='big')

        # XOR hashed value with master share
        int_pseudo_share = hash_of_master_share_int ^ int_x

        print('XOR output =', int_pseudo_share)
        int_pseudo_share = common.modulo_p(self.p, int_pseudo_share)
        pseudo_share = int_pseudo_share.to_bytes(
            bytehelper.bytelen(int_pseudo_share), byteorder='big')

        assert isinstance(pseudo_share, bytes)
        return pseudo_share
 def choose_distinct_master_shares_x(self):
     """ dealer chooses distinct master share x_j for each participant
     """
     master_shares_x = common.list_of_random_in_modulo_p(self.n, self.hash_len,
                                              self.p)
     common.print_list_of_hex(master_shares_x, 'x')
     return master_shares_x # TODO: use yield to construct a generator
Esempio n. 4
0
    def split_secrets(self):
        """ Split secret in one step with Lin-Yeh algorithm """

        self.random_id = common.provide_id(self.n, self.hash_len, self.p)
        self.master_shares_x = common.list_of_random_in_modulo_p(
            self.n, self.hash_len, self.p)
        self.access_group_polynomial_coeffs()
        self.compute_all_pseudo_shares()
        self.compute_all_public_shares_M()

        return self.pseudo_shares
Esempio n. 5
0
def test_hash_same():
    """ set up Dealer object and check hash repeatability """

    # Create a Dealer
    dealer = Dealer(p256, n_participants, s_secrets, access_structures)

    # test hash function - it should be repeatable for the same Dealer object
    hash1 = common.hash(b'BYTESEQUENCE', dealer.hash_len,
                        dealer.hash_aes_nonce)
    hash2 = common.hash(b'BYTESEQUENCE', dealer.hash_len,
                        dealer.hash_aes_nonce)
    assert_equal(hash1, hash2)
Esempio n. 6
0
def test_list_of_random_in_modulo_p():
    """ test: list_of_random_in_modulo_p """
    dealer = Dealer(4099, n_participants, s_secrets, access_structures)

    n = 5
    randomList = common.list_of_random_in_modulo_p(n,
                                                   dealer.hash_len,
                                                   dealer.p)
    common.print_list_of_hex(randomList, 'test randomList')
    # check the length of the list
    assert_equal(len(randomList), n)
    # check the type of object in the list
    assert_equal(isinstance(randomList[0], bytes), True)
Esempio n. 7
0
def test_hash_different():
    """ different instances of Dealer should have different
        hash results as they have separate random AES nonces"""

    # Create a Dealer
    dealer1 = Dealer(p256, n_participants, s_secrets, access_structures)
    dealer2 = Dealer(p256, n_participants, s_secrets, access_structures)

    # test hash function - it should be different for distinct Dealers
    hash1 = common.hash(b'BYTESEQUENCE', dealer1.hash_len,
                        dealer1.hash_aes_nonce)
    hash2 = common.hash(b'BYTESEQUENCE', dealer2.hash_len,
                        dealer2.hash_aes_nonce)
    assert_not_equal(hash1, hash2)
Esempio n. 8
0
def test_shamir_polynomial_compute():
    dealer = Dealer(p256, n_participants, s_secrets, access_structures)
    dealer.access_group_polynomial_coeffs()
    # override coeffs
    dealer.d[0][0] = [bytes([0x05]), bytes([0x07])]

    coeffs = dealer.get_d_polynomial_coeffs(0, 0)
    secret_value = dealer.s_secrets[0]

    value = common.shamir_polynomial_compute(bytes([0x01]), coeffs,
                                             secret_value, dealer.p)
    assert_equal(value, 12 + s_secrets[0])

    value = common.shamir_polynomial_compute(bytes([0x02]), coeffs,
                                             secret_value, dealer.p)
    assert_equal(value, 38 + s_secrets[0])
Esempio n. 9
0
def test_access_group_polynomial_coeffs():
    """ test: access_group_polynomial_coeffs """

    A1 = (1, 3)
    # gamma1 is a group of users authorized to reconstruct s1
    gamma1 = [A1]
    gamma2 = [(1, 2), (2, 3)]  # A1, A2 implicitly
    gamma3 = [(1, 2, 3)
              ]  # to secret s3 only all 3 users together can gain access
    access_structures = [gamma1, gamma2, gamma3]

    # Create a Dealer
    dealer = Dealer(p256, n_participants, s_secrets, access_structures)

    # compute d coeffs
    dealer.access_group_polynomial_coeffs()

    # dealer.print_list_of_hex(dealer.d[1][1], 'd-1-1')
    # test output
    assert_equal(len(dealer.d), 3)
    assert_equal(len(dealer.d[0]), 1)
    assert_equal(len(dealer.d[1][1]), 1)
    assert_equal(len(dealer.d[2][0]), 2)

    # Test index out of range
    with assert_raises(IndexError):
        print('Test', common.print_list_of_hex(dealer.d[2][1], 'd-2-1'))
Esempio n. 10
0
def test_provide_id():
    dealer = Dealer(p256, n_participants, s_secrets, access_structures)

    id_list = common.provide_id(n_participants, dealer.hash_len, dealer.p)
    # check the length of the list
    assert_equal(len(id_list), n_participants)
    # check the type of object in the list
    assert_equal(isinstance(id_list[0], bytes), True)
    def split_secrets(self):
        """ Split secret in one step """

        self.random_id = common.provide_id(self.n, self.hash_len, self.p)
        self.master_shares_x = self.choose_distinct_master_shares_x()

        self.access_group_polynomial_coeffs()
        self.compute_all_pseudo_shares()
        self.compute_all_public_shares_M()
        
        return self.pseudo_shares
    def user_polynomial_value_B(self, i_secret, q_group, participant):
        assert(participant in self.access_structures[i_secret][q_group])

        print('user_polynomial_value_B for secret %d, group A %d '.format(i_secret, q_group))
        participant_id = self.random_id[participant-1]
        print('B value for user %d with ID %d'.format(participant, participant_id))

        coeffs = self.get_d_polynomial_coeffs(i_secret, q_group)
        secret_value = self.s_secrets[i_secret]

        # returns int
        return common.shamir_polynomial_compute(participant_id, coeffs, secret_value, self.p)
Esempio n. 13
0
    def access_group_polynomial_coeffs(self):
        """ for the qth qualified set of access group,
            the dealer chooses d0, d1, d2... dm in Zp modulo field
            to construct the polynomial
            f_q(x) = si + d1*x + d2*x^2 + ... + dm*x^(m-1)

            note: d0 corresponds to x^1, d1 corresponds to x^2
        """
        for gindex, gamma in enumerate(self.access_structures):
            print('gamma%d for secret s%d:' % (gindex, gindex))
            coeffs_for_A = []
            self.d.append([])

            for index, A in enumerate(gamma):
                coeffs_for_A = common.list_of_random_in_modulo_p(
                    len(A) - 1, self.hash_len, self.p)
                print('A%d: %r' % (index, A))
                common.print_list_of_hex(coeffs_for_A, 'polynomial coeff d')

                self.d[gindex].append(coeffs_for_A)
        return self.d
Esempio n. 14
0
    def combine_secret(self, i_secret, q_group, obtained_pseudo_shares):
        """
        combine a single secret in Lin-Yeh algorithm
        """
        if isinstance(obtained_pseudo_shares[0], bytes):
            obtained_shares_int = []
            for obtained_share in obtained_pseudo_shares:
                obtained_shares_int.append(
                    int.from_bytes(obtained_share, byteorder='big'))
            obtained_pseudo_shares = obtained_shares_int

        print('Obtained pseudo shares:', obtained_pseudo_shares)

        print('Access group:', self.access_structures[i_secret])
        assert (q_group <= len(self.access_structures[i_secret]))

        combine_sum = 0

        for b, Pb in enumerate(self.access_structures[i_secret][q_group]):

            print('\tb =', b)
            part_sum_B = (obtained_pseudo_shares[b] +
                          self.public_shares_M[i_secret][q_group][b]) % self.p
            print('\tB = U+M, B = %d, M=%d' %
                  (part_sum_B, self.public_shares_M[i_secret][q_group][b]))

            combine_product = 1
            for r, Pr in enumerate(self.access_structures[i_secret][q_group]):
                if r != b:
                    print('\t\tr =', r)
                    print('\t\tID_(b=%d) : %d, ID_(r=%d) : %d' %
                          (Pb, self.get_id_int(Pb), Pr, self.get_id_int(Pr)))
                    denominator = (self.get_id_int(Pr) -
                                   self.get_id_int(Pb)) % self.p
                    den_inverse = bytehelper.inverse_modulo_p(
                        denominator, self.p)
                    print('\t\tdenominator = %d\n its inverse = %d' %
                          (denominator, den_inverse))
                    part_product = (
                        (self.get_id_int(Pr)) % self.p * den_inverse) % self.p

                    combine_product *= part_product
                    print('\t\tpart_product', part_product)
                    print('\t\tcombine_product', combine_product)

            combine_sum += (part_sum_B * combine_product) % self.p
            print('\tcomb prod=%d, part_sum_B=%d, combined_sum=%d' %
                  (combine_product, part_sum_B, combine_sum))

        print("Combined sum, s%d = %d" % (i_secret, combine_sum % self.p))

        return common.modulo_p(self.p, combine_sum)
Esempio n. 15
0
    def split_secrets(self):
        """ High-level interface function.
            Use Shamir's scheme to share the keys used
            to encrypt secrets. """
        self.cipher_generate_keys()
        assert self.cipher_keys

        # Shamir polynomial for each access group
        self.access_group_polynomial_coeffs()
        assert self.d

        # ID for each participant
        self.random_id = common.provide_id(self.n, self.hash_len, self.p)

        self.cipher_encrypt_all_secrets()

        return self.compute_all_key_shares()
Esempio n. 16
0
    def combine_secret_key(self, i_secret, obtained_shares):
        """
        combine a single key in Herraz-Ruiz-Saez algorithm
        """
        print('Obtained pseudo shares:', obtained_shares)
        q_group = 0

        combine_sum = 0

        print('combine_secret_key for access structure {}',
              self.access_structures)

        for b, Pb in enumerate(self.access_structures[i_secret][q_group]):

            print('\tcurrent user {} with index {} ='.format(Pb, b))
            part_sum = obtained_shares[b] % self.p

            combine_product = 1
            for r, Pr in enumerate(self.access_structures[i_secret][q_group]):
                if r != b:
                    print('\t\tr =', r)
                    print('\t\tID_(b=%d) : %d, ID_(r=%d) : %d' %
                          (Pb, self.get_id_int(Pb), Pr, self.get_id_int(Pr)))

                    denominator = (self.get_id_int(Pr) -
                                   self.get_id_int(Pb)) % self.p
                    den_inverse = bytehelper.inverse_modulo_p(
                        denominator, self.p)
                    print('\t\tdenominator = %d\n its inverse = %d' %
                          (denominator, den_inverse))

                    part_product = (
                        (self.get_id_int(Pr)) % self.p * den_inverse) % self.p
                    combine_product *= part_product

                    print('\t\tpart_product', part_product)
                    print('\t\tcombine_product', combine_product)

            combine_sum += (part_sum * combine_product) % self.p
            print('\tcomb prod=%d, part_sum_B=%d, combined_sum=%d' %
                  (combine_product, part_sum, combine_sum))

        print("Combined sum, s%d = %d" % (i_secret, combine_sum % self.p))

        return common.modulo_p(self.p, combine_sum)
Esempio n. 17
0
def main():
    """ This example shows low-level functions for splitting
        and combining secrets with multi-secret sharing
        scheme by Roy & Adhikari. """

    # large prime from NIST P-256 elliptic curve
    p256 = 2**256 - 2**224 + 2**192 + 2**96 - 1

    # multi secret sharing parameters
    s_secrets = [7, 313, 671]  # s_i
    n_participants = 3
    # access structure: to which secret what group has access
    # Gamma(s_i) = [A1, A2, ... Al], Aq = (P1, P2, Pm), q=1,2...l
    A1 = [1, 3]
    # gamma1 is a group of users authorized to reconstruct s1
    gamma1 = [A1]
    gamma2 = [[1, 2], [2, 3]]  # A1, A2 implicitly
    gamma3 = [[1, 2,
               3]]  # to secret s3 only all 3 users together can gain access
    access_structures = [gamma1, gamma2, gamma3]
    # TODO: in GUI choosing access structures on a matrix

    # Create a Dealer
    dealer = multisecret.MultiSecretRoyAdhikari.Dealer(p256, n_participants,
                                                       s_secrets,
                                                       access_structures)

    dealer.random_id = common.provide_id(
        n_participants, dealer.hash_len,
        dealer.p)  # a list of IDs stored internally
    dealer.master_shares_x = dealer.choose_distinct_master_shares_x()

    dealer.access_group_polynomial_coeffs()
    dealer.compute_all_pseudo_shares()
    dealer.compute_all_public_shares_M()

    print('obtained shares', dealer.pseudo_shares[0][0])
    obtained_shares = []
    for share in dealer.pseudo_shares[0][0]:
        obtained_shares.append(int.from_bytes(share, byteorder='big'))

    print('obtained shares', obtained_shares)
    combined_secret = dealer.combine_secret(0, 0, obtained_shares)
    print('Combined secret s1', combined_secret)
Esempio n. 18
0
    def compute_all_key_shares(self):

        self.key_shares = copy.deepcopy(self.access_structures)
        print(self.access_structures)

        for i, gamma in enumerate(self.access_structures):
            for q, A in enumerate(self.access_structures[i]):
                for b, Pb in enumerate(self.access_structures[i][q]):

                    print('secret_value (cipher_key)', self.cipher_keys[i])
                    secret_value = int.from_bytes(self.cipher_keys[i],
                                                  byteorder='big')
                    self.key_shares[i][q][b] = \
                        common.shamir_polynomial_compute(self.random_id[b],
                                                     self.d[i][q],
                                                     secret_value,
                                                     self.p)
                    print(
                        'Key share = {} for user {} (index {}) and secret {}'.
                        format(self.key_shares[i][q][b], Pb, b, i))

        return self.key_shares
Esempio n. 19
0
def test_modulo_p():
    p = 1009
    dealer = Dealer(p, n_participants, s_secrets, access_structures)
    assert_equal(common.modulo_p(p, 2011), 1002)