Pass root password directly to SDK again.

Related to this: https://github.com/lbryio/wallet-sync-server/issues/4

Passing in a KDF output messes with the existing CLI UI for wallet locking. Also the SDK has its own encryption from password, may as well use it.
This commit is contained in:
Daniel Krol 2022-08-08 16:31:29 -04:00
parent 165bcf1964
commit 6c9b9d07b2
3 changed files with 48 additions and 41 deletions

View file

@ -24,7 +24,7 @@ Generating keys...
Done generating keys Done generating keys
Registered Registered
>>> c1.salt_seed >>> c1.salt_seed
'fd7bcc62d7334fbf07aca5791783cb173e3aaef91e228f000a69e3ec8eef123e' '1d52635c14b34f0fefcf86368d4e0b82e3555de9d3c93a6f22cd5500fd120c0d'
``` ```
Set up the other client. See that it got the same salt seed from the server in the process, which it needs to make sure we have the correct encryption key and login password. Set up the other client. See that it got the same salt seed from the server in the process, which it needs to make sure we have the correct encryption key and login password.
@ -34,16 +34,16 @@ Set up the other client. See that it got the same salt seed from the server in t
Generating keys... Generating keys...
Done generating keys Done generating keys
>>> c2.salt_seed >>> c2.salt_seed
'fd7bcc62d7334fbf07aca5791783cb173e3aaef91e228f000a69e3ec8eef123e' '1d52635c14b34f0fefcf86368d4e0b82e3555de9d3c93a6f22cd5500fd120c0d'
``` ```
Now that the account exists, grab an auth token with both clients. Now that the account exists, grab an auth token with both clients.
``` ```
>>> c1.get_auth_token() >>> c1.get_auth_token()
Got auth token: 310077f33a9b8de99ee6c45ffbe4a06a7178683e4eb65500fc5ae26513f80928 Got auth token: e52f6e893fe3fa92d677d85f32e77357d68afd313c303a91d3af176ec684aa0d
>>> c2.get_auth_token() >>> c2.get_auth_token()
Got auth token: cdd18033dc48aeefedc278d116a6abbef7f0fb525d7ddfb2e1804a817a212c4a Got auth token: b9fc2620990447d5f0305ecafc9f75e2a5f928a31bd86806aa8989567cad57d0
``` ```
## Syncing ## Syncing
@ -55,7 +55,7 @@ Create a new wallet + metadata (we'll wrap it in a struct we'll call `WalletStat
>>> c1.update_remote_wallet() >>> c1.update_remote_wallet()
Successfully updated wallet state on server Successfully updated wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=1, encrypted_wallet='czo4MTkyOjE2OjE6KY46kZ0oRC9W8g/LVCe3V3sLdCHk0sWEBqPjzcKykl3dDJpQvRXtz8HFXlD+bgvs8M5jHw7KjJ9ODUOEq3VoSawrKyZpgc8AYIx+vC4w+q6cKC3LToxr7FlfyAoQKo9dCothik/90ySVMAPY1BBrBmQ8H46eFEoMWZ4nG2OWGew=') WalletState(sequence=1, encrypted_wallet='czo4MTkyOjE2OjE6XBEQgEACPvxgUFW3MGnY9tG5VYh/Hx7iNG6DAX+q4zTbVZM17OQ/5D1+IOjxS7jxOB+dZmtxmo6qwGtizjc4+YBhNk/eKb+uIU8T6HQ4T3m+PiWpedLnBwF4RStPPBp1M2WNFTIZQPKirETPO3GqRQSzveB17A3iESqYTqHnGeE=')
'Success' 'Success'
``` ```
@ -67,7 +67,7 @@ Now, call `init_wallet_state` with the other client. Then, we call `get_remote_w
>>> c2.init_wallet_state() >>> c2.init_wallet_state()
>>> c2.get_remote_wallet() >>> c2.get_remote_wallet()
Got latest walletState: Got latest walletState:
WalletState(sequence=1, encrypted_wallet='czo4MTkyOjE2OjE6KY46kZ0oRC9W8g/LVCe3V3sLdCHk0sWEBqPjzcKykl3dDJpQvRXtz8HFXlD+bgvs8M5jHw7KjJ9ODUOEq3VoSawrKyZpgc8AYIx+vC4w+q6cKC3LToxr7FlfyAoQKo9dCothik/90ySVMAPY1BBrBmQ8H46eFEoMWZ4nG2OWGew=') WalletState(sequence=1, encrypted_wallet='czo4MTkyOjE2OjE6XBEQgEACPvxgUFW3MGnY9tG5VYh/Hx7iNG6DAX+q4zTbVZM17OQ/5D1+IOjxS7jxOB+dZmtxmo6qwGtizjc4+YBhNk/eKb+uIU8T6HQ4T3m+PiWpedLnBwF4RStPPBp1M2WNFTIZQPKirETPO3GqRQSzveB17A3iESqYTqHnGeE=')
'Success' 'Success'
``` ```
@ -79,12 +79,12 @@ Push a new version, GET it with the other client. Even though we haven't edited
>>> c2.update_remote_wallet() >>> c2.update_remote_wallet()
Successfully updated wallet state on server Successfully updated wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=2, encrypted_wallet='czo4MTkyOjE2OjE6pNxAvxzGvZZvlSuYhSdGFmHGvWImYJlEewOnp6iUBbqTo899MrCfgvvlOzBOuKwk4vpJYcQgEkb3u2+j7bnJ18OCFEUeDzq88JuoKNw6ppdAbpw8D7MIDZP4Tf+5O8LmjxKtbiMy/ztW0nUxi4Ls8uuJ436CdF0UwaevHOAvlOE=') WalletState(sequence=2, encrypted_wallet='czo4MTkyOjE2OjE6gL9aGNjy4U+6mBQZRzx+GS+/1dhl54+5sBzVtBQz51az7HQ3HFI2PjUL7XkeTcjdsaPEKh3eFTQwly9fNFKJIya5YvmtY8zhxe8FCqCkTITrn2EPwZFYXF6E3Wi1gLaPMpZlb2EXIZ1E7Gbg1Uxcpj+s1CB4ttjIZdnFwUrfAw4=')
'Success' 'Success'
>>> c1.get_remote_wallet() >>> c1.get_remote_wallet()
Nothing to merge. Taking remote walletState as latest walletState. Nothing to merge. Taking remote walletState as latest walletState.
Got latest walletState: Got latest walletState:
WalletState(sequence=2, encrypted_wallet='czo4MTkyOjE2OjE6pNxAvxzGvZZvlSuYhSdGFmHGvWImYJlEewOnp6iUBbqTo899MrCfgvvlOzBOuKwk4vpJYcQgEkb3u2+j7bnJ18OCFEUeDzq88JuoKNw6ppdAbpw8D7MIDZP4Tf+5O8LmjxKtbiMy/ztW0nUxi4Ls8uuJ436CdF0UwaevHOAvlOE=') WalletState(sequence=2, encrypted_wallet='czo4MTkyOjE2OjE6gL9aGNjy4U+6mBQZRzx+GS+/1dhl54+5sBzVtBQz51az7HQ3HFI2PjUL7XkeTcjdsaPEKh3eFTQwly9fNFKJIya5YvmtY8zhxe8FCqCkTITrn2EPwZFYXF6E3Wi1gLaPMpZlb2EXIZ1E7Gbg1Uxcpj+s1CB4ttjIZdnFwUrfAw4=')
'Success' 'Success'
``` ```
@ -110,12 +110,12 @@ The wallet is synced between the clients. The client with the changed preference
>>> c1.update_remote_wallet() >>> c1.update_remote_wallet()
Successfully updated wallet state on server Successfully updated wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=3, encrypted_wallet='czo4MTkyOjE2OjE6FvtBsBMaRvnY6+SnQiBab/FWjzC9mgu3OHFXRTcJm3MsByZWbrzkFz6y4FrPN1cC+/Rcw11oJNydyys2ZaPl6zNYP/uxV6anEmET1hTt1+E2NzUJ2K/K4BLN7AgLBLQDM8zAwVzCTeaT6MZvjTV/slYc7NEqlfCMgeId2WpBJp+BCbTLo0SjPWhHCsQvo3Hf') WalletState(sequence=3, encrypted_wallet='czo4MTkyOjE2OjE6JwVggGDjqoLy9YUqFXzIltph5bvO46SwJoAbLydlLg1mjfoXksGm9NsWbmYYmBoiXmiIbJPIsj8xfOjO5JlCH+EHSdyjCXizzwClYwgM4UD1+/ltuv1TH7H59cXd6Kztefn4y9IL/97rs+2DxDHM6cb/AdYGohIc3VaCmYBSbYRQFjTbQHaaScW6ntYuXAyE')
'Success' 'Success'
>>> c2.get_remote_wallet() >>> c2.get_remote_wallet()
Nothing to merge. Taking remote walletState as latest walletState. Nothing to merge. Taking remote walletState as latest walletState.
Got latest walletState: Got latest walletState:
WalletState(sequence=3, encrypted_wallet='czo4MTkyOjE2OjE6FvtBsBMaRvnY6+SnQiBab/FWjzC9mgu3OHFXRTcJm3MsByZWbrzkFz6y4FrPN1cC+/Rcw11oJNydyys2ZaPl6zNYP/uxV6anEmET1hTt1+E2NzUJ2K/K4BLN7AgLBLQDM8zAwVzCTeaT6MZvjTV/slYc7NEqlfCMgeId2WpBJp+BCbTLo0SjPWhHCsQvo3Hf') WalletState(sequence=3, encrypted_wallet='czo4MTkyOjE2OjE6JwVggGDjqoLy9YUqFXzIltph5bvO46SwJoAbLydlLg1mjfoXksGm9NsWbmYYmBoiXmiIbJPIsj8xfOjO5JlCH+EHSdyjCXizzwClYwgM4UD1+/ltuv1TH7H59cXd6Kztefn4y9IL/97rs+2DxDHM6cb/AdYGohIc3VaCmYBSbYRQFjTbQHaaScW6ntYuXAyE')
'Success' 'Success'
>>> c2.get_preferences() >>> c2.get_preferences()
{'animal': 'cow', 'car': ''} {'animal': 'cow', 'car': ''}
@ -142,7 +142,7 @@ One client POSTs its change first.
>>> c1.update_remote_wallet() >>> c1.update_remote_wallet()
Successfully updated wallet state on server Successfully updated wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=4, encrypted_wallet='czo4MTkyOjE2OjE6rKE6TWvZxBp0No0S1CRrjW55i6w9pE6obS+9bwR76qaBBQ40lz0Ajd/2vXO1KBAQhxEHDJ6WJLPs15SgqhVspaNXmdwR1dYEHmJ8M+PW0KLv+vZoxxeGQ/5EBdrAZIfBhmI50SPF4RzmTzKTyw3VlSdqqhCutgi6FcXP+CLlsnH6qaLgjLDLISjwSMIwBd4y') WalletState(sequence=4, encrypted_wallet='czo4MTkyOjE2OjE6xMKOvjQ9RBAWCac5Cj5d30YSI4PaMh3T+99fLdHKJC2RCcwrbhCurNIDBln6QJWCfa3gRp2/sY9k47XwZNsknCTrdIe4c3YJejvL/WCZTzoJ81m9QGbP/05DHQUV5c7z30taIESp4qOFwpSwYMB972gn6ZXOhn1iNDKSCLN3nSLHFnA0arjCAPQof//lJriz')
'Success' 'Success'
``` ```
@ -154,7 +154,7 @@ Eventually, the client will be responsible (or at least more responsible) for me
>>> c2.get_remote_wallet() >>> c2.get_remote_wallet()
Merging local changes with remote changes to create latest walletState. Merging local changes with remote changes to create latest walletState.
Got latest walletState: Got latest walletState:
WalletState(sequence=4, encrypted_wallet='czo4MTkyOjE2OjE6rKE6TWvZxBp0No0S1CRrjW55i6w9pE6obS+9bwR76qaBBQ40lz0Ajd/2vXO1KBAQhxEHDJ6WJLPs15SgqhVspaNXmdwR1dYEHmJ8M+PW0KLv+vZoxxeGQ/5EBdrAZIfBhmI50SPF4RzmTzKTyw3VlSdqqhCutgi6FcXP+CLlsnH6qaLgjLDLISjwSMIwBd4y') WalletState(sequence=4, encrypted_wallet='czo4MTkyOjE2OjE6xMKOvjQ9RBAWCac5Cj5d30YSI4PaMh3T+99fLdHKJC2RCcwrbhCurNIDBln6QJWCfa3gRp2/sY9k47XwZNsknCTrdIe4c3YJejvL/WCZTzoJ81m9QGbP/05DHQUV5c7z30taIESp4qOFwpSwYMB972gn6ZXOhn1iNDKSCLN3nSLHFnA0arjCAPQof//lJriz')
'Success' 'Success'
>>> c2.get_preferences() >>> c2.get_preferences()
{'animal': 'horse', 'car': 'Audi'} {'animal': 'horse', 'car': 'Audi'}
@ -166,12 +166,12 @@ Finally, the client with the merged wallet pushes it to the server, and the othe
>>> c2.update_remote_wallet() >>> c2.update_remote_wallet()
Successfully updated wallet state on server Successfully updated wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=5, encrypted_wallet='czo4MTkyOjE2OjE62Tub/EfwCMdYpZ9N9wCRwTB3Di+eA0oVpn44v/n1UgOB8jNEIEtQptCfBtBE7yfIJP8pw544SkhxAfR2Zy8/UrLIhKMUSVeCl8bJP78AoJCPpeJEQo4GOqPvluWYS2eOh1urZojn5yqB5nGRnK4hYhQ6lOwgg4jfRFtTzMKPYb263ONb3mx1SkeoCwmBeRoF') WalletState(sequence=5, encrypted_wallet='czo4MTkyOjE2OjE6L+PCpF1qh1ayai/fqnc7kwa2eBJc1n6L6FuaLps8gdZhY9UdaBMc/BckvgUF9OXR7yOvndrFy73+5EzWxpmffBfZGqq42XjtbmHGScEERjuzra8UB2vLn+N2oe5s+e2O+7lJxPKYBD2pX4xKm3HjKqAso+D0MsWHMz9hqRLFekJfv5pVglUVkweW+h8yNxn1')
'Success' 'Success'
>>> c1.get_remote_wallet() >>> c1.get_remote_wallet()
Nothing to merge. Taking remote walletState as latest walletState. Nothing to merge. Taking remote walletState as latest walletState.
Got latest walletState: Got latest walletState:
WalletState(sequence=5, encrypted_wallet='czo4MTkyOjE2OjE62Tub/EfwCMdYpZ9N9wCRwTB3Di+eA0oVpn44v/n1UgOB8jNEIEtQptCfBtBE7yfIJP8pw544SkhxAfR2Zy8/UrLIhKMUSVeCl8bJP78AoJCPpeJEQo4GOqPvluWYS2eOh1urZojn5yqB5nGRnK4hYhQ6lOwgg4jfRFtTzMKPYb263ONb3mx1SkeoCwmBeRoF') WalletState(sequence=5, encrypted_wallet='czo4MTkyOjE2OjE6L+PCpF1qh1ayai/fqnc7kwa2eBJc1n6L6FuaLps8gdZhY9UdaBMc/BckvgUF9OXR7yOvndrFy73+5EzWxpmffBfZGqq42XjtbmHGScEERjuzra8UB2vLn+N2oe5s+e2O+7lJxPKYBD2pX4xKm3HjKqAso+D0MsWHMz9hqRLFekJfv5pVglUVkweW+h8yNxn1')
'Success' 'Success'
>>> c1.get_preferences() >>> c1.get_preferences()
{'animal': 'horse', 'car': 'Audi'} {'animal': 'horse', 'car': 'Audi'}
@ -202,7 +202,7 @@ We try to POST both of them to the server. The second one fails because of the c
>>> c2.update_remote_wallet() >>> c2.update_remote_wallet()
Successfully updated wallet state on server Successfully updated wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=6, encrypted_wallet='czo4MTkyOjE2OjE6ZNErNr5SrgjRMOBmK2pKtU2wu+jdwR8WO/thAf+VrGJ9237sKTjNX0aQILuj9dOzY836xYk2vB1Niypgf4PvlnXEAZ64pHO2FV8aR/0JcjsufkdUXUIJH2hxDhT5Ui8kS2tXPAuo0xDxfqQgqiJaVNfgyCo2fzqz5m5V3jBzivm7fN8TpuNaT94koI2GFPc3') WalletState(sequence=6, encrypted_wallet='czo4MTkyOjE2OjE6HieQoVznUMTBF6x643Mg/AQUZadaikkiuRZsw3IaQsapK56WL3IBGrlemOjSH6uTfBWsWaLDMXEz+X7j5wqchSAt/wle2+I9dKgyDdFhWMOaEd61pT6r+lS8O8AbSKUJ6r5FSDgJRE/vz5l4xP/W9AVrK4l0u9ZqpvsKAet3UlfVV48cOnhwgPqlPoGBQ1xF')
'Success' 'Success'
>>> c1.update_remote_wallet() >>> c1.update_remote_wallet()
Submitted wallet is out of date. Submitted wallet is out of date.
@ -218,14 +218,14 @@ The client that is out of date will then call `get_remote_wallet`, which GETs an
>>> c1.get_remote_wallet() >>> c1.get_remote_wallet()
Merging local changes with remote changes to create latest walletState. Merging local changes with remote changes to create latest walletState.
Got latest walletState: Got latest walletState:
WalletState(sequence=6, encrypted_wallet='czo4MTkyOjE2OjE6ZNErNr5SrgjRMOBmK2pKtU2wu+jdwR8WO/thAf+VrGJ9237sKTjNX0aQILuj9dOzY836xYk2vB1Niypgf4PvlnXEAZ64pHO2FV8aR/0JcjsufkdUXUIJH2hxDhT5Ui8kS2tXPAuo0xDxfqQgqiJaVNfgyCo2fzqz5m5V3jBzivm7fN8TpuNaT94koI2GFPc3') WalletState(sequence=6, encrypted_wallet='czo4MTkyOjE2OjE6HieQoVznUMTBF6x643Mg/AQUZadaikkiuRZsw3IaQsapK56WL3IBGrlemOjSH6uTfBWsWaLDMXEz+X7j5wqchSAt/wle2+I9dKgyDdFhWMOaEd61pT6r+lS8O8AbSKUJ6r5FSDgJRE/vz5l4xP/W9AVrK4l0u9ZqpvsKAet3UlfVV48cOnhwgPqlPoGBQ1xF')
'Success' 'Success'
>>> c1.get_preferences() >>> c1.get_preferences()
{'animal': 'beaver', 'car': 'Toyota'} {'animal': 'beaver', 'car': 'Toyota'}
>>> c1.update_remote_wallet() >>> c1.update_remote_wallet()
Successfully updated wallet state on server Successfully updated wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=7, encrypted_wallet='czo4MTkyOjE2OjE6csXFcg5GaaIXauqORyfoSo3rcKiWzmTE2M/YBIJ1wmdBafqtUnKSO8DE/3EeKA35ow8iXJy5mowe4Ar8R+7m6FHxDblkDohjoeP9uZ5ziEirMSPu4eZsOcpXLdBsHp/qcGpNKAFnwGqeSdrxjvyFDQCyjl204mduE/X9mh6mlyYIei1IkK08rSTmc7mCuxIj') WalletState(sequence=7, encrypted_wallet='czo4MTkyOjE2OjE6ypuX2e/wjiVZZVrLQEwoEuHZH7xhs6B3/awzxH/5WZITlKOo7TvV2Mjke/MSdTk2/YyWhfN8U0e4IwGxKW9VIpnF3ElEtEZxvJBklzDXeDNh5pWMgeZkBH5EempDQ6VzT0206z89EeiCK+3QSofUv7Ob90xNVUOdJq5/OBrG4LAGFh2ZVrh5KnqDm1+d8/ls')
'Success' 'Success'
``` ```
@ -243,7 +243,7 @@ Generating keys...
Done generating keys Done generating keys
Successfully updated password and wallet state on server Successfully updated password and wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=8, encrypted_wallet='czo4MTkyOjE2OjE6p5qwc7BWPjZE6sDI6To/dS5wVDMvzb6BA9oezrp3ecVryouLorggVTmnQLpcLdskBDNjE7/S5P4T4LT6hJCjAby2LCgeHuatDrySson8RHcs9rozLFoaPIQCDMkCPC8EGTN/g0aOAnDGvB6jaW/IsSLpMyXeth2OjloOtj2caT1hrihpThFrLPp4glBRLGL5') WalletState(sequence=8, encrypted_wallet='czo4MTkyOjE2OjE6Kd/DnozNDXYia8yYqrVI6OJ56tDAo5X4/Il+Ein/E6GRQ6K8/niK8Sjx1Cmpf7ecru14QS51pTwlFpS9mbwNE7CZ1wjAZHoLlL5B+dAECkSCFBHgBvq/29cXt6gG7KP+TLRLxZzGtgQRQiq6fsMBIIirw1ZCmpUNQP/PCHIJRfjJS0MNAGN8+srlPv+eUXIn')
'Success' 'Success'
``` ```
@ -251,7 +251,7 @@ We generate a new salt seed when we change the password
``` ```
>>> c1.salt_seed >>> c1.salt_seed
'9968ede44e397d7875c057e4ebe50fd1118dc43a3e404e134353be6224947aad' '155b6e8a9a8c9406844b6b0c4a40c3204ab1f06668470faa89e28aa89fefe3cf'
``` ```
This operation invalidates all of the user's auth tokens. This prevents other clients from accidentally pushing a wallet encrypted with the old password. This operation invalidates all of the user's auth tokens. This prevents other clients from accidentally pushing a wallet encrypted with the old password.
@ -271,17 +271,19 @@ The client that changed its password can easily get a new token because it has t
``` ```
>>> c1.get_auth_token() >>> c1.get_auth_token()
Got auth token: 796ea0575fe1ba5d6a43afec016f6ed2c9225a5180e76e744aad5b8857c8702b Got auth token: 68a3db244e21709429e69e67352d02a3b26542c5ef2ac3377e19b17de71942d6
>>> c2.get_auth_token() >>> c2.get_auth_token()
Error 401 Error 401
b'{"error":"Unauthorized: No match for email and/or password"}\n' b'{"error":"Unauthorized: No match for email and/or password"}\n'
Failed to get the auth token. Do you need to update this client's password (set_local_password())?
Or, in the off-chance the user changed their password back and forth, try updating secrets (update_secrets()) to get the latest salt seed.
>>> c2.set_local_password("eggsandwich") >>> c2.set_local_password("eggsandwich")
Generating keys... Generating keys...
Done generating keys Done generating keys
>>> c2.salt_seed >>> c2.salt_seed
'9968ede44e397d7875c057e4ebe50fd1118dc43a3e404e134353be6224947aad' '155b6e8a9a8c9406844b6b0c4a40c3204ab1f06668470faa89e28aa89fefe3cf'
>>> c2.get_auth_token() >>> c2.get_auth_token()
Got auth token: 61932e198643b6f8bf1cd42fd0d296ce01b9813b6c1f312826baca3d50f95d47 Got auth token: 3917215675c5cc7fb5c5e24d583fddcd0a14c4370140e2274cf4c5da7eaae7bb
``` ```
We don't allow password changes if we have pending wallet changes to push. This is to prevent a situation where the user has to merge local and remote changes in the middle of a password change. We don't allow password changes if we have pending wallet changes to push. This is to prevent a situation where the user has to merge local and remote changes in the middle of a password change.
@ -297,13 +299,13 @@ Local changes found. Update remote wallet before changing password.
>>> c1.update_remote_wallet() >>> c1.update_remote_wallet()
Successfully updated wallet state on server Successfully updated wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=9, encrypted_wallet='czo4MTkyOjE2OjE6i9/lJoTH+8okCoczA7Q0o/X/X8MfVulO3qAq2GtKEKW9m4JH7Fcup62BOhwHtsNPOHIiMv9er5SpOx9pGBq3s9Bei4k2fNq4RXmXEPZX66p1T26VboJ0o53etIhnfQ9Q3pdLssiURjkK4OXpDDzbw1KsYXAPnJS50Nb8/A7+14BTgLoyJmGjW3nwjTxFjzRt') WalletState(sequence=9, encrypted_wallet='czo4MTkyOjE2OjE6Hspn+wbfHEzSv+1zsM/sFUaJJZuLLP7jLtCl3Ou3OQhXGEpkC0pP7WcbdGdQ+4foakTaB/y/b9All85rJ1ZiGWFnaK8SS9Rd7JT1UCEHs0BhN5+SfIK58yukIefzP39ZlSGUomE3eifOqso8C/gY2FltO96TS8WXx6czxqm6M/dvLk6q10LpODCQEH5auTA6')
'Success' 'Success'
>>> c1.change_password("starboard") >>> c1.change_password("starboard")
Generating keys... Generating keys...
Done generating keys Done generating keys
Successfully updated password and wallet state on server Successfully updated password and wallet state on server
Synced walletState: Synced walletState:
WalletState(sequence=10, encrypted_wallet='czo4MTkyOjE2OjE6D2TVSTbVugAqf8VSDmiIbArhQypf6o1LkQxAphJFlcbHHDtCQ4aqpmhsdWrkaf0Jd7+L2J12aWNf+XQGwS/kddTi9pplCwlAJB/RkTl4xeFPIRT5g5iVHrJcvCU2/gNa1BpRGtROn0fFb0SscS3WPxdQ5QA6jIGEblu1OY0KF/phpQt1DtNcuOS6rOz3NCmV') WalletState(sequence=10, encrypted_wallet='czo4MTkyOjE2OjE6Cnditb9t+rU56hfcMq6gW+lx1ek3TzyBZ4633FoiWCzTxIenbMyapolU0gnpWHasP8olOoL56LfSGVzP8eKG4JoRsU9VmOYXjkpY9QZCcKomVC4fJ17jPq/e2gJWDSv03pA1xbDhRpXRnZr3wd+37znTUyLpYzRDRAHpb2IGDi9FforobQRNcZUhx0DY8WIR')
'Success' 'Success'
``` ```

2
test_client/gen-readme.py Normal file → Executable file
View file

@ -1,3 +1,5 @@
#!/bin/python3
# Generate the README since I want real behavior interspersed with comments # Generate the README since I want real behavior interspersed with comments
# Come to think of it, this is accidentally a pretty okay integration test for client and server # Come to think of it, this is accidentally a pretty okay integration test for client and server
# NOTE - delete the database before running this, or else you'll get an error for registering. also we want the wallet to start empty # NOTE - delete the database before running this, or else you'll get an error for registering. also we want the wallet to start empty

View file

@ -248,7 +248,7 @@ def derive_secrets(root_password, email, salt_seed):
scrypt_p = 1 scrypt_p = 1
key_length = 32 key_length = 32
num_keys = 3 num_keys = 2
salt = generate_salt(email, salt_seed) salt = generate_salt(email, salt_seed)
@ -268,14 +268,12 @@ def derive_secrets(root_password, email, salt_seed):
parts = ( parts = (
kdf_output[:key_length], kdf_output[:key_length],
kdf_output[key_length:key_length * 2], kdf_output[key_length:key_length * 2],
kdf_output[key_length * 2:],
) )
lbry_id_password = base64.b64encode(parts[0]).decode('utf-8') lbry_id_password = base64.b64encode(parts[0]).decode('utf-8')
sync_password = base64.b64encode(parts[1]).decode('utf-8') hmac_key = parts[1]
hmac_key = parts[2]
return lbry_id_password, sync_password, hmac_key return lbry_id_password, hmac_key
def create_hmac(wallet_state, hmac_key): def create_hmac(wallet_state, hmac_key):
input_str = str(wallet_state.sequence) + ':' + wallet_state.encrypted_wallet input_str = str(wallet_state.sequence) + ':' + wallet_state.encrypted_wallet
@ -324,7 +322,7 @@ class Client():
# be a new seed if it's a new server. # be a new seed if it's a new server.
self.salt_seed = generate_salt_seed() self.salt_seed = generate_salt_seed()
self.lbry_id_password, self.sync_password, self.hmac_key = derive_secrets( self.lbry_id_password, self.hmac_key = derive_secrets(
self.root_password, self.email, self.salt_seed) self.root_password, self.email, self.salt_seed)
success = self.wallet_sync_api.register( success = self.wallet_sync_api.register(
@ -350,7 +348,7 @@ class Client():
locally. locally.
""" """
self.salt_seed = self.wallet_sync_api.get_salt_seed(self.email) self.salt_seed = self.wallet_sync_api.get_salt_seed(self.email)
self.lbry_id_password, self.sync_password, self.hmac_key = derive_secrets( self.lbry_id_password, self.hmac_key = derive_secrets(
self.root_password, self.email, self.salt_seed) self.root_password, self.email, self.salt_seed)
# TODO - This does not deal with the question of tying accounts to wallets. # TODO - This does not deal with the question of tying accounts to wallets.
@ -495,7 +493,7 @@ class Client():
return "Error" return "Error"
submitted_wallet_state = WalletState( submitted_wallet_state = WalletState(
encrypted_wallet=self.get_local_encrypted_wallet(self.sync_password), encrypted_wallet=self.get_local_encrypted_wallet(self.root_password),
sequence=self.synced_wallet_state.sequence + 1 sequence=self.synced_wallet_state.sequence + 1
) )
hmac = create_hmac(submitted_wallet_state, self.hmac_key) hmac = create_hmac(submitted_wallet_state, self.hmac_key)
@ -525,8 +523,14 @@ class Client():
# Auditor - Should we be generating a *new* seed for every password change? # Auditor - Should we be generating a *new* seed for every password change?
self.salt_seed = generate_salt_seed() self.salt_seed = generate_salt_seed()
new_lbry_id_password, new_sync_password, new_hmac_key = derive_secrets( new_lbry_id_password, new_hmac_key = derive_secrets(
new_root_password, self.email, self.salt_seed) new_root_password, self.email, self.salt_seed)
def set_secrets():
# Only do this once we got a good response from the server.
# In a function because it can happen in two different places.
self.root_password, self.lbry_id_password, self.hmac_key = (
new_root_password, new_lbry_id_password, new_hmac_key)
# TODO - Think of failure sequence in case of who knows what. We # TODO - Think of failure sequence in case of who knows what. We
# could just get the old salt seed back from the server? # could just get the old salt seed back from the server?
# We can't lose it though. Keep the old one around? Kinda sucks. # We can't lose it though. Keep the old one around? Kinda sucks.
@ -553,7 +557,7 @@ class Client():
# accepted by the server. # accepted by the server.
submitted_wallet_state = WalletState( submitted_wallet_state = WalletState(
encrypted_wallet=self.get_local_encrypted_wallet(new_sync_password), encrypted_wallet=self.get_local_encrypted_wallet(new_root_password),
sequence=self.synced_wallet_state.sequence + 1 sequence=self.synced_wallet_state.sequence + 1
) )
hmac = create_hmac(submitted_wallet_state, new_hmac_key) hmac = create_hmac(submitted_wallet_state, new_hmac_key)
@ -562,9 +566,9 @@ class Client():
updated = self.wallet_sync_api.change_password_with_wallet(submitted_wallet_state, hmac, self.email, self.lbry_id_password, new_lbry_id_password, self.salt_seed) updated = self.wallet_sync_api.change_password_with_wallet(submitted_wallet_state, hmac, self.email, self.lbry_id_password, new_lbry_id_password, self.salt_seed)
if updated: if updated:
# We updated it. Now it's synced and we mark it as such. Update everything in one command to keep local changes in sync! # We updated it. Now it's synced and we mark it as such. Update everything at once to keep local changes in sync!
self.synced_wallet_state, self.lbry_id_password, self.sync_password, self.hmac_key = ( self.synced_wallet_state = submitted_wallet_state
submitted_wallet_state, new_lbry_id_password, new_sync_password, new_hmac_key) set_secrets()
print ("Synced walletState:") print ("Synced walletState:")
pprint(self.synced_wallet_state) pprint(self.synced_wallet_state)
@ -574,9 +578,8 @@ class Client():
updated = self.wallet_sync_api.change_password_no_wallet(self.email, self.lbry_id_password, new_lbry_id_password, self.salt_seed) updated = self.wallet_sync_api.change_password_no_wallet(self.email, self.lbry_id_password, new_lbry_id_password, self.salt_seed)
if updated: if updated:
# We updated it. Now we mark it as such. Update everything in one command to keep local changes in sync! # We updated it. Now we mark it as such. Update everything at once to keep local changes in sync!
self.lbry_id_password, self.sync_password, self.hmac_key = ( set_secrets()
new_lbry_id_password, new_sync_password, new_hmac_key)
return "Success" return "Success"
print ("Could not update wallet and password. Perhaps need to get new wallet and merge, perhaps something else.") print ("Could not update wallet and password. Perhaps need to get new wallet and merge, perhaps something else.")
@ -603,7 +606,7 @@ class Client():
def update_local_encrypted_wallet(self, encrypted_wallet): def update_local_encrypted_wallet(self, encrypted_wallet):
# TODO - error checking # TODO - error checking
return LBRYSDK.update_wallet(self.wallet_id, self.sync_password, encrypted_wallet) return LBRYSDK.update_wallet(self.wallet_id, self.root_password, encrypted_wallet)
def get_local_encrypted_wallet(self, sync_password): def get_local_encrypted_wallet(self, sync_password):
# TODO - error checking # TODO - error checking