def DeriveKey(args): global groupObj assert groupObj != None, "groupObj not set" if type(args) in [tuple, list]: # first use hash to ZR # then hash to a key return hashPair(groupObj.hash(args, ZR)) else: # hash directly to a key return hashPair(args)
def extract_key(g): """ Given a group element, extract a symmetric key :param g: :return: """ g_in_hex = hashPair(g).decode('utf-8') return bytes(bytearray.fromhex(g_in_hex))
def encrypt(self, plain, public_keys, category, parties): """ Encrypt a given plain message of a specific category for given parties. The message itself will be encryped with AES, but the session key will be encrypted with CP-ABE. The category will be encoded in the cipher. @param plain Message to encrypt. Can be text or binary data. @param public_keys Dictionary of public keys per category. @param category Category of message @param parties List of parties allowed to decrypt this message. @return Encrypted message with header @throws KeyRingError if no public key is available for category """ # Validate parameters public_keys = self.clean_keys(public_keys) category = self.clean_category(category) parties = self.clean_parties(parties) # Unpack key try: pk = public_keys[category] except LookupError: raise KeyRingError("No public key available for category %s" % category) # Create result buffer result = io.BytesIO() # Initialize AES aes_iv = Random.new().read(AES.block_size) aes_key_plain = self.group.random(GT) aes_key_cipher = self.scheme.encrypt(pk, aes_key_plain, parties) aes_key_cipher["category"] = category aes_key_bytes = objectToBytes(aes_key_cipher, self.group) aes_key_size = len(aes_key_bytes) aes = AES.new(hashPair(aes_key_plain)[0:32], AES.MODE_CFB, aes_iv) # Write header result.write(bytes(aes_iv)) result.write(struct.pack("<Q", aes_key_size)) result.write(aes_key_bytes) # Encrypt data plain_padded = pad_message(plain, AES.block_size) plain_padded_checksum = hashlib.sha1(plain_padded).hexdigest() result.write(plain_padded_checksum) result.write(aes.encrypt(plain_padded)) # Done return base64.b64encode(result.getvalue())
def tokengen(self, attr_key, d_u, Q_cloud): h = group.random(ZR) # pairing.element tk = {} policy_str = util.createPolicy(attr_key['policy']) attr_list = util.getAttributeList(policy_str) tmp = int.from_bytes(hashPair(Q_cloud ** d_u),'big') # python 3.X bytes to int sharekey = group.init(ZR,tmp) for x in attr_list: y = util.strip_index(x) tk[y] = attr_key['Du'][y] / h + sharekey if debug: print(str(y) + " tk[y] " + str(tk[y])) if debug: print("Access Policy for key: %s" % attr_key['policy']) if debug: print("Attribute list: %s" % attr_list) TK = {'policy': attr_key['policy'], 'token':tk} return TK, h
def encrypt(self, pk, M, attr_list): if debug: print('Encryption Algorithm...') k = group.random(ZR); Cs = pk ** k Ci = {} for attr in attr_list: Ci[attr] = self.attribute[attr] ** k symcrypt = SymmetricCryptoAbstraction(hashPair(Cs)) C = symcrypt.encrypt(M) # HMAC # from charm.toolbox.symcrypto import MessageAuthenticator # m = MessageAuthenticator(extract_key(key)) # AuthenticatedMessage = m.mac('Hello World') return { 'C': C, 'Ci': Ci,'attributes': attr_list }
def CLoud_decrypt(self, C, TK, d_cloud, Q_u): policy = util.createPolicy(TK['policy']) attrs = util.prune(policy, C['attributes']) if attrs == False: return False coeff = util.getCoefficients(policy) Z = {} prodT = 1 tmp = int.from_bytes(hashPair(Q_u ** d_cloud),'big') # python 3.X bytes to int sharekey = group.init(ZR,tmp) for i in range(len(attrs)): x = attrs[i].getAttribute() y = attrs[i].getAttributeAndIndex() Z[y] = C['Ci'][x] ** (TK['token'][x] - sharekey) prodT *= Z[y] ** coeff[y] return prodT
def combine_coin_shares(self, shares, nonce): ''' Combines the coin shares by forming a threshold signature and taking its 1st bit, subsequently it verifies the result. NOTE: combining shares should always succeed except when some of the shares were invalid or the dealer was dishonest, in which case the toss might be biased and should ideally be discarded :param dict shares: keys are processes ids, values are shares (group G1 elements) :param string nonce: the nonce the shares were created for -- necessary for verifying the result of combining :returns: pair (int, bool) : (coin toss in {0,1}) , (whether combining shares was succesful) ''' # there are enough shares of a coin assert len(shares) == self.threshold, 'Not enough shares for combining' signature = self.verification_key.combine_shares(shares) hex_string = hashPair(signature).decode() # we just use the first bit as the coin toss coin_value = bytes.fromhex(hex_string)[0] % 2 # verify the result nonce_hash = self.verification_key.hash_fct(nonce) correctness = self.verification_key.verify_signature(signature, nonce_hash) return (coin_value, correctness)
def decrypt(self, C, prodT,h): symcrypt = SymmetricCryptoAbstraction(hashPair(prodT*h)) return symcrypt.decrypt(C['C'])