Non-custodial Wallet Hosting & Sync
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 7.2k
- Forks
- 493
- PR merge metrics
- No merged PRs in 30d
Description
(draft)
Motivation
Your wallet file stores important data that apps need to access. There's no convenient noncustodial way to back up your wallet or keep it synced across multiple apps. If you use several LBRY apps, you'll end up with many separate wallets.
Goals
| name | description |
|---|---|
noncustodial |
host has no access to information inside wallet |
multiapp |
multiple apps can use (odysee, lbry desktop, hound.fm, etc) |
onepw |
single password for wallet encryption and app login (prolly via lbry.id oauth) |
pwreset |
password can be changed, and can be reset if forgotten in some cases. some data loss is acceptable here |
realtime |
|
decentralized |
the whole setup can be run by anyone |
userfriendly |
losing access to your wallet is as hard as we can make it |
Plan
1. move as much stuff out of the wallet as possible
- channel keys come from seed (lex already working on this https://github.com/lbryio/lbry-sdk/issues/1433)
- subscriptions go on-chain?
- app settings stored in
encrypted blob in channel?unsynced, or the sync is done by the app
2. hosted wallet sync and oauth
set up https://lbry.id service to host wallets and provide oauth (should be open-source and documented so anyone can run their own auth service)
support 2fa?
3. client-side signing via lbry.id or js or browser plugin (a la metamask)
Once this sync protocol is adopted, apps will need a way for users to sign transactions to interact with LBRY. This must be done client side to satisfy the noncustodial requirement. This can be done (in increasing order of security) custom in the app via JS, or using a popup like Deso, or a browser extension like Metamask (which could also do hardware wallet support).
Terms
- version (uint)
- The protocol version used to encrypt the wallet. This document describes version 1 of the protocol.
- id (string)
- A string that uniquely identifies a user. If this is an email address, we get the benefit of being able to contact the user if necessary.
- password (string)
- The password as the user enters it.
- rootKey (bytes)
- A cryptographic key derived from the password using a key derivation function (KDF)
- walletKey (bytes)
- The first half of the root key. This key is used to encrypt a user's wallet. It is only used locally on a user's device and is never sent to the server.
- loginKey (bytes)
- The second half of the root key. This key is used to authenticate a user with the server.
- sequence (uint)
- A counter that is incremented every time a wallet is updated. This prevents race conditions where multiple simultaneous writes overwrite one another.
- authToken (bytes)
- A token representing a user session.
- mfaCode (uint)
- The TOTP code from a multi-factor device (Authenticator app, etc)
- wallet (bytes)
- Plaintext private user data. May include seed phrases, private keys, app info, settings, etc.
- encryptedWallet (bytes)
- `wallet` data that is encrypted and may be shared securely.
Server Operations
register
Register a new account
params: id, password, version
response: authToken
errors: version not supported, id already exists
oauth
Support the standard Oauth flows. We'll probably integrate with existing IDP project
getWallet
Get the current wallet data
params: authToken
response: version, encryptedWallet, sequence
errors: invalid authToken
putWallet
Store new wallet data
params: authToken, version, encryptedWallet, sequence
response: ok
errors: invalid authToken, version not supported, sequence mismatch
changePassword
This is the same as a putWallet, but also changes the loginKey.
params: authToken, version, loginKey, encryptedWallet, sequence
response: ok
errors: invalid authToken, version not supported, sequence mismatch
info
Get info about a user
params: authToken
response: id, version, sequence
websocket
Connect to websocket to be notified when new wallet data is stored
params: authToken
Common flows
New account
TODO
Connect an app
TODO
Conflicting writes
TODO
I forgot my password, what can I do?
- recovery from paper backup
- changing password if unlocked wallet is/isnt available
- changing password if active auth is/isnt available
TODO
Multiple user apps (desktop + mobile + paper backup)
TODO
- how to handle when a password was changed on another app
- recovery via another app
UX Considerations
Different wallets have different needs. If you just started an account, its no big deal to lose your wallet. If you have a lot of channels/claims/lbc in there, you want more backups and security.
Security
how to do this so its secure? what's the threat model?
prolly want an audit for this, but shouldn't block deployment
Rabbit holes
password resets
oauth and multiple apps
secure client-side signing via lbry.id
migrating odysee to this system
phishing
do we have to have the same password across multiple apps?
Extras
When unlocking, run sync first to make sure latest version is stored in cloud
Unlock via QR code or copying a string?
optional passcode to wrap root key locally
encrypt data with intermediate key, then encrypt that key with the password. this lets you back up your wallet encrpytion key on paper
does this work with multiple apps? can you have separate passwords across multiple apps? prolly not… so then a malicious app could get your odysee password
can you login with zksnarks? proof you know some encrypted string without revealing that string?
tell ppl when their passwords are poor using haveibeenpwned.com
outline what changes sdk has to make
should we store an updatedAt timestamp for wallet changes?
Alternative ideas
no wallets. everything is on-chain and can be restored from seed
- makes every settings change a txn. may lead to scaling issues
- we should assume our blockchain will be upgraded to handle this
- where do we store the data? its not always tied to channels
- plus side: if we can do this, we won't need lbry.id to host wallets. every app can do its own thing.
store wallet in public cloud (s3, google drive, etc). define storage location in channel claim.
- doesnt meet
onepwrequirement - wallets aren't tied to channels, so we'd need a new place on-chain to store them
Related issues
https://github.com/lbryio/lbry-sdk/issues/2641
References
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the related issue 2641 and the referenced encryption and identity specifications. Resolve the TODOs covering account flows, conflicting writes, recovery, and multiple apps, then define the threat model and required SDK changes. Done means the wallet sync protocol and server operations are specified well enough to implement.
Written by the indexing model from the issue text.
Assessment
- Domain
- authentication, backend-api-design, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 15/100