-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuser_app.py
More file actions
140 lines (116 loc) · 6.16 KB
/
user_app.py
File metadata and controls
140 lines (116 loc) · 6.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
from legacy.contracts import LegacyUserContract, Wallet, Ethereum
from util.cipher import AESCipher
from util.util import purge
from secretsharing import SecretSharer, PlaintextToHexSecretSharer
from cryptography.fernet import Fernet
from hashlib import sha256
import sys, os
import config
# TO-DO:
# - n must be at least 2.
# - test decrypt
# - test everything actually
# - deprecate fernet and use AES instead
# - store hashes of secrets in the contract
ETH_ACCOUNTS = (
'0xjjqcouv812rdguinvu9izlsgnhg0t6rahwnzw3ae',
'0x87akw04kssvmlvvqssl8gvpnghzbmz99oatx0m0h',
'0xy7ei3dyk3y9ruprxavhbde5qajzm34zpcviufyen',
'0xc0kgh2crlk1wdfkn4ldha0d4lel0kmv4ue86wegu',
'0x1rfle3wewrd1psmb0obl8s3as8p296ap5w7phgac'
)
# in practice, obtained through metamask
USER_ADDRESS = '0xfsefjzd1vpmxokklf6l5n091jatlam4286onamfs'
def populate_system():
for i in range(0, len(ETH_ACCOUNTS)):
account_i = Wallet(ETH_ACCOUNTS[i])
account_i.save()
def store_file_in_ipfs(message, filename=""):
# emulates file storage in ipfs
index = 'Qm' + sha256(message).hexdigest()
if not filename:
filename = index
file_path = os.path.join(config.DATA_DIR, filename)
with open(file_path + '.txt', 'w') as the_file:
the_file.write(message)
#return '/ipfs/' + file_name
return index
def get_personal_key():
# returns a 44-char string
return Fernet.generate_key()
if __name__ == '__main__':
if '--fresh' in sys.argv:
purge() # deletes all state data previously stored
populate_system() # creates some wallets to use as beneficiaries
print "#####################################################################"
print "####################### View: User #################################"
print "#####################################################################"
print "\n"
print "Set up your Legacy smart contract. Please provide the following information:"
print "(note: Legacy won't store any kind of sensible data)\n"
print "### Step 1: Your Beneficiaries"
print "Existing Ethereum accounts:"
for i in range(0, len(ETH_ACCOUNTS)):
print "\t" + ETH_ACCOUNTS[i]
beneficiaries_tmp = []
personal_keys = []
finished = False
finished_input = ""
i = 0
while not finished:
address_i = str(raw_input("Ethereum wallet address of beneficiary " + str(i) + ":\n" ))
# TODO: if address doesn't exist, create it ?
message_i = raw_input("What secret message would you like to leave to this person:\n")
personal_key_i = get_personal_key()
personal_keys.append(personal_key_i)
cipher_suite = Fernet(personal_key_i)
enc_message_i = cipher_suite.encrypt(message_i)
funds_share_i = raw_input("Share of your funds that you'd like to transfer to this beneficiary (eg. 25%):\n" )
beneficiaries_tmp.append({'wallet_address': address_i, 'enc_message': enc_message_i, 'funds_share': funds_share_i})
finished_input = raw_input("Have you finished adding beneficiaries (yes/no)?\n")
while finished_input not in ['yes', 'no']:
finished_input = raw_input("Not a valid answer. Try again\n")
finished = True if finished_input == 'yes' else False
i = i + 1
print "\n### Step 2: The Shared Key"
n = i # number of beneficiaries
secret = raw_input("Now, enter a random phrase that will be used to create your secret password (eg. 'I love cats').\n")
secret = secret.lower()
print "Your secret will be shared among " + str(n) + " persons. How many of them will be required to restore it?\n"
k = int(raw_input("Please enter an integer k such that 2 <= k < " + str(n) + "\n"))
secret_pieces = PlaintextToHexSecretSharer.split_secret(secret, k, n)
# create encryption object based on shared secret
aes_cipher = AESCipher(secret)
beneficiaries = []
for i in range (0, n):
# now that we have the shared secret, apply an additional encryption layer
doub_enc_message_i = aes_cipher.encrypt(beneficiaries_tmp[i]['enc_message'])
message_url_i = store_file_in_ipfs(doub_enc_message_i)
address_i = beneficiaries_tmp[i]['wallet_address']
funds_share_i = beneficiaries_tmp[i]['funds_share']
# save the beneficiary dict in array (note that we don't store sensible data)
beneficiaries.append({'wallet_address': address_i, 'message_url': message_url_i,
'funds_share': funds_share_i, 'secret_piece_hash': sha256(secret_pieces[i]).hexdigest()})
print "\n### Step 3: Proof of Life"
print "You will need to give signs of life periodically."
print "If you fail to so for a time greater than T, we'll assume you are dead."
t_PoL = int(raw_input("Please enter a value for T (in days):\n"))
user_contract = LegacyUserContract(k, n, t_PoL, 0, beneficiaries, USER_ADDRESS)
user_contract.save() # saving with default name 'user_contract'
print "#####################################################################"
print "#################### contract successfully created ! ################"
print "#####################################################################"
print "\n"
print "IMPORTANT: To each one of your beneficiaries, you must give a *secret piece* along with a *personal decryption password*"
print "If you pass away, your dead man switch can only be activated if "+str(k)+" out of "+str(n)+" secret pieces are recovered."
print "After that, your beneficiaries will need their *personal decryption password* to decrypt the messages you sent them."
print "Backup this information carefully, and make sure to close this application."
print "\n"
for i in range (0, n):
print "- address " + beneficiaries[i]['wallet_address']
print " secret piece: " + secret_pieces[i]
print " personal decryption password: " + personal_keys[i]
print "\n"
print "#####################################################################"
print "######################### program completed #########################"
print "#####################################################################"