def test_create_combine(self): values = ["N17FigASkL6p1EOgJhRaIquQLGvYV0", "0y10VAfmyH7GLQY6QccCSLKJi8iFgpcSBTLyYOGbiYPqOpStAf1OYuzEBzZR", "KjRHO1nHmIDidf6fKvsiXWcTqNYo2U9U8juO94EHXVqgearRISTQe0zAjkeUYYBvtcB8VWzZHYm6ktMlhOXXCfRFhbJzBUsXaHb5UDQAvs2GKy6yq0mnp8gCj98ksDlUultqygybYyHvjqR7D7EAWIKPKUVz4of8OzSjZlYg7YtCUMYhwQDryESiYabFID1PKBfKn5WSGgJBIsDw5g2HB2AqC1r3K8GboDN616Swo6qjvSFbseeETCYDB3ikS7uiK67ErIULNqVjf7IKoOaooEhQACmZ5HdWpr34tstg18rO"] minimum = [4, 6, 20] shares = [5, 100, 100] sss = sssa() for index,value in enumerate(values): self.assertEqual(sss.combine(sss.create(minimum[index], shares[index], value)), value)
def test_library_combine(self): sss = sssa() shares = [ "U1k9koNN67-og3ZY3Mmikeyj4gEFwK4HXDSglM8i_xc=yA3eU4_XYcJP0ijD63Tvqu1gklhBV32tu8cHPZXP-bk=", "O7c_iMBaGmQQE_uU0XRCPQwhfLBdlc6jseTzK_qN-1s=ICDGdloemG50X5GxteWWVZD3EGuxXST4UfZcek_teng=", "8qzYpjk7lmB7cRkOl6-7srVTKNYHuqUO2WO31Y0j1Tw=-g6srNoWkZTBqrKA2cMCA-6jxZiZv25rvbrCUWVHb5g=", "wGXxa_7FPFSVqdo26VKdgFxqVVWXNfwSDQyFmCh2e5w=8bTrIEs0e5FeiaXcIBaGwtGFxeyNtCG4R883tS3MsZ0=", "j8-Y4_7CJvL8aHxc8WMMhP_K2TEsOkxIHb7hBcwIBOo=T5-EOvAlzGMogdPawv3oK88rrygYFza3KSki2q8WEgs=" ] self.assertEqual(sss.combine(shares), "test-pass")
def recover_mnemonic(password, secrets): shares = [] # type(secrets) key = binascii.unhexlify(password) for secret in secrets: data = binascii.unhexlify(secret) nonce, tag = data[:12], data[-16:] cipher = AES.new(key, AES.MODE_GCM, nonce) shares.append(cipher.decrypt_and_verify(data[12:-16], tag)) sss = sssa() mnemonic = sss.combine(shares) return mnemonic
def test_create_combine(self): values = [ "N17FigASkL6p1EOgJhRaIquQLGvYV0", "0y10VAfmyH7GLQY6QccCSLKJi8iFgpcSBTLyYOGbiYPqOpStAf1OYuzEBzZR", "KjRHO1nHmIDidf6fKvsiXWcTqNYo2U9U8juO94EHXVqgearRISTQe0zAjkeUYYBvtcB8VWzZHYm6ktMlhOXXCfRFhbJzBUsXaHb5UDQAvs2GKy6yq0mnp8gCj98ksDlUultqygybYyHvjqR7D7EAWIKPKUVz4of8OzSjZlYg7YtCUMYhwQDryESiYabFID1PKBfKn5WSGgJBIsDw5g2HB2AqC1r3K8GboDN616Swo6qjvSFbseeETCYDB3ikS7uiK67ErIULNqVjf7IKoOaooEhQACmZ5HdWpr34tstg18rO" ] minimum = [4, 6, 20] shares = [5, 100, 100] sss = sssa() for index, value in enumerate(values): self.assertEqual( sss.combine(sss.create(minimum[index], shares[index], value)), value)
def split_mnemonic(key_salt_array, mnemonic, minimum_required, total_shares): """ Derive an Scrypt key with the user's email with salt, this should be secure as email's are unique Now the key which is being generated, must be used to encrypt the mnemonic, this encrypted ciphertext must be appended with the tag and nonce, ciphertext must be hex encoded and then must be split into different shares Output: salt: bytes shares: list of str """ #ciphertext, tag, nonce = aes_encrypt(key2, mnemonic) ##ciphertest must be appended with tag and nonce so that MAC can be checked ##while decryption #ciphertext = b"".join([tag, ciphertext, nonce]) ##hex encoding of ciphertext, the shamor secret will fail if its avoided #hexlified_ciphertext = binascii.hexlify(ciphertext) sss = sssa() ##breaking hexlified_ciphertext with shamir secrets shares = sss.create(minimum_required, total_shares, mnemonic) ##this salt will be kep in admin database, against this user mnemonic new_list = [] for ((key, salt), secret) in zip(key_salt_array, shares): _key, _salt = binascii.unhexlify(key), binascii.unhexlify(salt) ciphertext, tag, nonce = aes_encrypt(_key, secret) ##ciphertest must be appended with tag and nonce so that MAC can be checked ##while decryption ciphertext = b"".join([tag, ciphertext, nonce]) ##hex encoding of ciphertext, the shamor secret will fail if its avoided hexlified_ciphertext = binascii.hexlify(ciphertext) new_list.append({ "key": key, "salt": salt, "secret": binascii.hexlify(ciphertext) }) return new_list
def combine_mnemonic(secret_salt_array): ##ARGs: ## shares:str must be a list of shamir secrets, ## must be minimum required when secrets were created ##generating scrypt key on the basis of email and salt new_list = [] for (key, salt, secret) in secret_salt_array: _key, _salt, _secret = binascii.unhexlify(key), binascii.unhexlify(salt),\ binascii.unhexlify(secret) decrypted_share = aes_decrypt(_key, _secret) ##ciphertest must be appended with tag and nonce so that MAC can be checked ##while decryption new_list.append(decrypted_share) ##hex encoding of ciphertext, the shamor secret will fail if its avoided #hexlified_ciphertext = binascii.hexlify(ciphertext) #new_list.append({"key": key, "salt": salt, "secret": ciphertext}) sss = sssa() ##Combining all the shamir secrets, this will fail if the minimum secrets ##requirement will not be fulfilled mnemonic = sss.combine(new_list) return mnemonic
def mnemonic(email, phone_number, password): r = requests.post("http://%s/getkeys" % ip, data=json.dumps({ "email": email, "phone_number": phone_number })) shares = [] try: key = binascii.unhexlify(password) for secret in r.json()["data"].keys(): data = binascii.unhexlify(r.json()["data"][secret]) nonce, tag = data[:12], data[-16:] cipher = AES.new(key, AES.MODE_GCM, nonce) shares.append(cipher.decrypt_and_verify(data[12:-16], tag)) except Exception as e: return json.dumps({"success": False, "error": str(e)}) sss = sssa() mnemonic = sss.combine(shares) return mnemonic
def test_library_combine(self): sss = sssa() shares = ["U1k9koNN67-og3ZY3Mmikeyj4gEFwK4HXDSglM8i_xc=yA3eU4_XYcJP0ijD63Tvqu1gklhBV32tu8cHPZXP-bk=", "O7c_iMBaGmQQE_uU0XRCPQwhfLBdlc6jseTzK_qN-1s=ICDGdloemG50X5GxteWWVZD3EGuxXST4UfZcek_teng=", "8qzYpjk7lmB7cRkOl6-7srVTKNYHuqUO2WO31Y0j1Tw=-g6srNoWkZTBqrKA2cMCA-6jxZiZv25rvbrCUWVHb5g=", "wGXxa_7FPFSVqdo26VKdgFxqVVWXNfwSDQyFmCh2e5w=8bTrIEs0e5FeiaXcIBaGwtGFxeyNtCG4R883tS3MsZ0=", "j8-Y4_7CJvL8aHxc8WMMhP_K2TEsOkxIHb7hBcwIBOo=T5-EOvAlzGMogdPawv3oK88rrygYFza3KSki2q8WEgs="] self.assertEqual(sss.combine(shares), "test-pass")
def aes_decrypt(key, ciphertext, nonce): cipher = AES.new(key, AES.MODE_EAX, nonce) data = cipher.decrypt(ciphertext) return data.decode("utf-8") def generate_key_pair(): key = RSA.generate(2048) pubkey = key.publickey().export_key() privkey = key.export_key() return pubkey, privkey # Shamir's Secret Sharing sss = sssa() def divide_secret(secret, k, n): return sss.create(k, n, secret) def combine_secret(secret_pieces): return sss.combine(secret_pieces) # Digital Signature def sign(key, msg): signer = pkcs1_15.new(RSA.import_key(key))