コード例 #1
0
ファイル: TestPolynomial.py プロジェクト: HRodriguez/svelib
 def test_create_coeff_polynomial_small(self):
     """
     Create a new coefficients polynomial by giving the corresponding 
     coefficients (small modulus and coefficients example, for easy 
     reading).
     """
     # Generate our polynomial:
     # p(x) = x^2 + 4*x + 8 \in Z_{17} (ie. modulus 17 algebra)
     modulus = 17
     coefficients = [8, 4, 1] # coefficients[i] is c_{i} in SUM(c_{i}*x^i)
     p = CoefficientsPolynomial(modulus, coefficients)
     
     # Test that the resulting polynomial has the expected degree: 2
     self.assertEqual(p.get_degree(), 2)
     
     # Test that the modulus and coefficients were correctly recorded
     self.assertEqual(p.get_modulus(), modulus)
     self.assertEqual(p.get_coefficients(), coefficients)
     
     for i in range(0, len(coefficients)):
         self.assertEqual(p.get_coefficient(i), coefficients[i])
         
     # Test that the polynomial evaluates to the expected value for a few 
     # x's
     
     # 1) p(5) = 5^2 + 4*5 + 8 = 25 + 20 + 8 = 53 = 2 mod 17
     self.assertEqual(p(5), 2)
     # 2) p(1) = 1 + 4 + 8 = 13 = 13 mod 17
     self.assertEqual(p(1), 13)
     # 3) p(0) = 8 mod 17
     self.assertEqual(p(0), 8)
     # 4) p(16) = 16^2 + 4*16 + 8 = 256 + 64 + 8 = 328 = 5 mod 17
     self.assertEqual(p(16), 5)
     
     # The following examples are currently valid, although 
     # CoefficientsPolynomial could be altered to not allow calls with 
     # numbers outside of [0, modulus - 1]:
     
     # 5) p(90) = p(5) % 17 = 2 mod 17 (see 1, and (90 = 5) mod 17)
     self.assertEqual(p(90), 2)
     # 6) p(-12) = p(5) % 17 = 2 mod 17 (see 1, and (-12 = 5) mod 17)
     self.assertEqual(p(-12), 2)
コード例 #2
0
    def test_get_coeff_out_of_range(self):
        """
        Test that trying to get a coefficient by index where the given index is 
        not between 0 and the degree of the polynomial - 1, inclusive, results 
        in an exception being raised.
        """
        # Generate our polynomial:
        # p(x) = x^2 + 4*x + 8 \in Z_{17} (ie. modulus 17 algebra)
        modulus = 17
        coefficients = [8, 4, 1]
        p = CoefficientsPolynomial(modulus, coefficients)

        self.assertRaises(ValueError, p.get_coefficient, -1)
        self.assertRaises(ValueError, p.get_coefficient, len(coefficients))
コード例 #3
0
    def test_create_coeff_polynomial_small(self):
        """
        Create a new coefficients polynomial by giving the corresponding 
        coefficients (small modulus and coefficients example, for easy 
        reading).
        """
        # Generate our polynomial:
        # p(x) = x^2 + 4*x + 8 \in Z_{17} (ie. modulus 17 algebra)
        modulus = 17
        coefficients = [8, 4, 1]  # coefficients[i] is c_{i} in SUM(c_{i}*x^i)
        p = CoefficientsPolynomial(modulus, coefficients)

        # Test that the resulting polynomial has the expected degree: 2
        self.assertEqual(p.get_degree(), 2)

        # Test that the modulus and coefficients were correctly recorded
        self.assertEqual(p.get_modulus(), modulus)
        self.assertEqual(p.get_coefficients(), coefficients)

        for i in range(0, len(coefficients)):
            self.assertEqual(p.get_coefficient(i), coefficients[i])

        # Test that the polynomial evaluates to the expected value for a few
        # x's

        # 1) p(5) = 5^2 + 4*5 + 8 = 25 + 20 + 8 = 53 = 2 mod 17
        self.assertEqual(p(5), 2)
        # 2) p(1) = 1 + 4 + 8 = 13 = 13 mod 17
        self.assertEqual(p(1), 13)
        # 3) p(0) = 8 mod 17
        self.assertEqual(p(0), 8)
        # 4) p(16) = 16^2 + 4*16 + 8 = 256 + 64 + 8 = 328 = 5 mod 17
        self.assertEqual(p(16), 5)

        # The following examples are currently valid, although
        # CoefficientsPolynomial could be altered to not allow calls with
        # numbers outside of [0, modulus - 1]:

        # 5) p(90) = p(5) % 17 = 2 mod 17 (see 1, and (90 = 5) mod 17)
        self.assertEqual(p(90), 2)
        # 6) p(-12) = p(5) % 17 = 2 mod 17 (see 1, and (-12 = 5) mod 17)
        self.assertEqual(p(-12), 2)
コード例 #4
0
ファイル: TestPolynomial.py プロジェクト: HRodriguez/svelib
    def test_create_coeff_polynomial_large_random(self):
        """
        Create a new coefficients polynomial by giving the modulus and 
        generating random coefficients (large modulus and coefficients example, 
        for stress testing).
        """
        # 4096-bit prime
        prime = int(\
                    "1030799842786894181631389441103185966569507239371816962" \
                    "4978338055490842089614129277498900319820357566344123748" \
                    "6733156317168957900155665107496366703386281755055392965" \
                    "0482922853287292659506843149296105637767886823281017653" \
                    "3910493192845060890137468614986408838534331249499143887" \
                    "8240392751996416013109700510089131594462789759613994845" \
                    "8435523590438946151771098557650151249388764789950580302" \
                    "5724273343076818749635035686807909690718552859584015925" \
                    "7687323419195652187155387082468433670807387493556016980" \
                    "5863461555878279456798001719303987238011908109139830602" \
                    "0669938885067728431660759420938086503333708168951681838" \
                    "3021541449655465434898294213951276050509787120108201138" \
                    "0714497759152490923615704418043118467768563572708275773" \
                    "2461440591991675120453490718568934924138096603098071715" \
                    "5809020294969435729482955533673603467176342000620072339" \
                    "9031249881813572203253808727332410548412729356180978096" \
                    "4888225806099431563543317084150424777724002753141453195" \
                    "1549167254419629309482949167419204154625159927438070053" \
                    "2255709285198635275092329304750758901073929816789775100" \
                    "3853339241804019013946059652824339135601164264716579746" \
                    "0752798419181115878818875144812516179341148144694010500" \
                    "1197785456808159638017068703237966891009241058822845094" \
                    "404308191065131495323419")

        # Generate our polynomial:
        degree = 50
        p = CoefficientsPolynomial.new_random_polynomial(prime, degree)
        
        # Test that the resulting polynomial has the expected degree and 
        # modulus
        self.assertEqual(p.get_degree(), degree)
        self.assertEqual(p.get_modulus(), prime)
        
        # Get the polynomial coefficients
        coefficients = p.get_coefficients()
        self.assertEqual(len(coefficients) - 1, degree)
        
        # define our own calculation of the polynomial value for a given x
        # using a recursive version of Horner's scheme
        def expected_value(x, coeffs):
            if(len(coeffs) == 0):
                return 0
            else:
                # If p(x) = SUM{c_i*x^i} for i \in [0,n]
                # and q(x) = SUM{c_{i+1}*x^i} for i \in [0,n-1], then:
                # p(x) = q(x)*x + c_{0}
                q = expected_value(x, coeffs[1:])
                return (q*x + coeffs[0]) % prime
                
        # test some random values
        for i in range(0, 50):
            x = random.randint(0, prime)
            self.assertEqual(p(x), expected_value(x, coefficients))
コード例 #5
0
    def test_create_coeff_polynomial_large_random(self):
        """
        Create a new coefficients polynomial by giving the modulus and 
        generating random coefficients (large modulus and coefficients example, 
        for stress testing).
        """
        # 4096-bit prime
        prime = int(\
                    "1030799842786894181631389441103185966569507239371816962" \
                    "4978338055490842089614129277498900319820357566344123748" \
                    "6733156317168957900155665107496366703386281755055392965" \
                    "0482922853287292659506843149296105637767886823281017653" \
                    "3910493192845060890137468614986408838534331249499143887" \
                    "8240392751996416013109700510089131594462789759613994845" \
                    "8435523590438946151771098557650151249388764789950580302" \
                    "5724273343076818749635035686807909690718552859584015925" \
                    "7687323419195652187155387082468433670807387493556016980" \
                    "5863461555878279456798001719303987238011908109139830602" \
                    "0669938885067728431660759420938086503333708168951681838" \
                    "3021541449655465434898294213951276050509787120108201138" \
                    "0714497759152490923615704418043118467768563572708275773" \
                    "2461440591991675120453490718568934924138096603098071715" \
                    "5809020294969435729482955533673603467176342000620072339" \
                    "9031249881813572203253808727332410548412729356180978096" \
                    "4888225806099431563543317084150424777724002753141453195" \
                    "1549167254419629309482949167419204154625159927438070053" \
                    "2255709285198635275092329304750758901073929816789775100" \
                    "3853339241804019013946059652824339135601164264716579746" \
                    "0752798419181115878818875144812516179341148144694010500" \
                    "1197785456808159638017068703237966891009241058822845094" \
                    "404308191065131495323419")

        # Generate our polynomial:
        degree = 50
        p = CoefficientsPolynomial.new_random_polynomial(prime, degree)

        # Test that the resulting polynomial has the expected degree and
        # modulus
        self.assertEqual(p.get_degree(), degree)
        self.assertEqual(p.get_modulus(), prime)

        # Get the polynomial coefficients
        coefficients = p.get_coefficients()
        self.assertEqual(len(coefficients) - 1, degree)

        # define our own calculation of the polynomial value for a given x
        # using a recursive version of Horner's scheme
        def expected_value(x, coeffs):
            if (len(coeffs) == 0):
                return 0
            else:
                # If p(x) = SUM{c_i*x^i} for i \in [0,n]
                # and q(x) = SUM{c_{i+1}*x^i} for i \in [0,n-1], then:
                # p(x) = q(x)*x + c_{0}
                q = expected_value(x, coeffs[1:])
                return (q * x + coeffs[0]) % prime

        # test some random values
        for i in range(0, 50):
            x = random.randint(0, prime)
            self.assertEqual(p(x), expected_value(x, coefficients))
コード例 #6
0
    def generate_commitment(self):
        """
		Generate a ThresholdEncryptionCommitment towards the threshold scheme.
		
		Returns:
			commitment::ThresholdEncryptionCommitment
		
		Throws:
			ThresholdEncryptionSetUpStateError -- If public keys are not loaded.
		"""
        # 0. Verify that all public keys are available for 1-to-1 encryption.
        for trustee in range(0, self._num_trustees):
            pk = self._trustees_simple_public_keys[trustee]
            if (pk == None):
                raise ThresholdEncryptionSetUpStateError(
                 "generate_commitment() must only be called after all the " \
                 "trustees' public keys have been registered with this " \
                 "ThresholdEncryptionSetUp instance. Missing public key " \
                 "for trustee %d." % trustee)

        # 1. Construct a new random polynomial of degree (threshold - 1)
        # Note: A polynomial of degree (t - 1) is determined by any t
        # (distinct) points.
        degree = self._threshold - 1
        nbits = self.cryptosystem.get_nbits()
        prime = self.cryptosystem.get_prime()
        generator = self.cryptosystem.get_generator()

        #  All calculations inside the polynomial are performed modulus q
        #  where q is such that p = 2*q + 1 (q is prime because of how we
        #  construct p when generating an EGCryptoSystem).
        #  We do this, because the values of the polynomial coefficients or its
        #  value at a certain point are always used as the exponent of elements
        #  in Z_{p}^{*}, and we know:
        #  a = b mod (p - 1) => g^a = g^b mod p
        #  (because g^{a-b} = g^{x(p-1)} = (g^x)^{p-1} = 1 mod p)
        #  We use q and not p - 1, because Z_{q} is a field (because q is
        #  prime), while the same would not be true for p-1, and we need the
        #  polynomials to be on a field in order to perform Lagrange
        #  Interpolation (see ThresholdDecryptionCombinator.decrypt_to_X()).
        #  This also means that 2*P(0) will be the threshold private key
        #  (never actually seen directly by the parties), and g^(2*P(0))
        #  the threshold public key.
        #  For the full explanation, see: (TODO: Add reference)

        q = (prime - 1) / 2
        polynomial = \
         CoefficientsPolynomial.new_random_polynomial(q, degree)

        # 2. Generate the public "coefficients" (actually g^coefficient for
        # each coefficient of the polynomial).
        public_coeficients = []
        for coeff in polynomial.get_coefficients():
            public_coeficients.append(pow(generator, coeff, prime))

        # 3. Generate the partial private keys for each trustee.
        # The partial private key for trustee j is P_{i}(j+1), with i the
        # trustee generating the commitment, its full private key is the sum
        # of the P_{i}(j+1) values generated by all trustees (including its own).
        # We must add 1 to the trustee index, since we want the trustee
        # indexes in the polynomial to start on 1, while our lists are 0
        # based.
        # (We must never reveal P(0) as this is the complete private key
        # of the full threshold scheme)

        # IMPORTANT: We encrypt each partial private key so that only its
        # intended recipient may read it.
        enc_partial_priv_keys = []
        for trustee in range(0, self._num_trustees):
            ppriv_key = polynomial(trustee + 1)  # P_{i}(j)
            trustee_pk = self._trustees_simple_public_keys[trustee]

            # Note that trustee public keys need not use the same cryptosystem
            # as the threshold encryption. In fact, they might not even have
            # the same bit length.
            bitstream = BitStream()
            bitstream.put_num(ppriv_key, nbits)
            ciphertext = trustee_pk.encrypt_bitstream(bitstream)
            enc_partial_priv_keys.append(ciphertext)

        # 4. Construct a ThresholdEncryptionCommitment object storing this
        # commitment and return it.
        return ThresholdEncryptionCommitment(self.cryptosystem,
                                             self._num_trustees,
                                             self._threshold,
                                             public_coeficients,
                                             enc_partial_priv_keys)
コード例 #7
0
	def generate_commitment(self):
		"""
		Generate a ThresholdEncryptionCommitment towards the threshold scheme.
		
		Returns:
			commitment::ThresholdEncryptionCommitment
		
		Throws:
			ThresholdEncryptionSetUpStateError -- If public keys are not loaded.
		"""
		# 0. Verify that all public keys are available for 1-to-1 encryption.
		for trustee in range(0, self._num_trustees):
			pk = self._trustees_simple_public_keys[trustee]
			if(pk == None):
				raise ThresholdEncryptionSetUpStateError(
					"generate_commitment() must only be called after all the " \
					"trustees' public keys have been registered with this " \
					"ThresholdEncryptionSetUp instance. Missing public key " \
					"for trustee %d." % trustee)
		
		# 1. Construct a new random polynomial of degree (threshold - 1)
		# Note: A polynomial of degree (t - 1) is determined by any t 
		# (distinct) points.
		degree = self._threshold - 1
		nbits = self.cryptosystem.get_nbits()
		prime = self.cryptosystem.get_prime()
		generator = self.cryptosystem.get_generator()
		
		#  All calculations inside the polynomial are performed modulus q
		#  where q is such that p = 2*q + 1 (q is prime because of how we 
		#  construct p when generating an EGCryptoSystem).
		#  We do this, because the values of the polynomial coefficients or its 
		#  value at a certain point are always used as the exponent of elements 
		#  in Z_{p}^{*}, and we know:
		#  a = b mod (p - 1) => g^a = g^b mod p
		#  (because g^{a-b} = g^{x(p-1)} = (g^x)^{p-1} = 1 mod p)
		#  We use q and not p - 1, because Z_{q} is a field (because q is 
		#  prime), while the same would not be true for p-1, and we need the 
		#  polynomials to be on a field in order to perform Lagrange 
		#  Interpolation (see ThresholdDecryptionCombinator.decrypt_to_X()). 
		#  This also means that 2*P(0) will be the threshold private key 
		#  (never actually seen directly by the parties), and g^(2*P(0)) 
		#  the threshold public key.
		#  For the full explanation, see: (TODO: Add reference)
		
		q = (prime - 1) / 2
		polynomial = \
			CoefficientsPolynomial.new_random_polynomial(q, degree)
		
		# 2. Generate the public "coefficients" (actually g^coefficient for 
		# each coefficient of the polynomial).
		public_coeficients = []
		for coeff in polynomial.get_coefficients():
			public_coeficients.append(pow(generator, coeff, prime)) 
		
		# 3. Generate the partial private keys for each trustee.
		# The partial private key for trustee j is P_{i}(j+1), with i the   
		# trustee generating the commitment, its full private key is the sum 
		# of the P_{i}(j+1) values generated by all trustees (including its own).
		# We must add 1 to the trustee index, since we want the trustee 
		# indexes in the polynomial to start on 1, while our lists are 0 
		# based.
		# (We must never reveal P(0) as this is the complete private key
		# of the full threshold scheme)
		
		# IMPORTANT: We encrypt each partial private key so that only its 
		# intended recipient may read it.
		enc_partial_priv_keys = []
		for trustee in range(0, self._num_trustees):
			ppriv_key = polynomial(trustee + 1) # P_{i}(j)
			trustee_pk = self._trustees_simple_public_keys[trustee]
			
			# Note that trustee public keys need not use the same cryptosystem 
			# as the threshold encryption. In fact, they might not even have 
			# the same bit length.
			bitstream = BitStream()
			bitstream.put_num(ppriv_key, nbits)
			ciphertext = trustee_pk.encrypt_bitstream(bitstream)
			enc_partial_priv_keys.append(ciphertext)
		
		# 4. Construct a ThresholdEncryptionCommitment object storing this 
		# commitment and return it.
		return ThresholdEncryptionCommitment(self.cryptosystem, 
			self._num_trustees, self._threshold, public_coeficients, 
			enc_partial_priv_keys)