lbryio / lbryio/lbry-sdk

Non-custodial Wallet Hosting & Sync

Open
#3,442 9 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area: wallet
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 wallets synced live between apps (at least it should feel like its live). relaxing this constraint since realtime stuff is moving out to federation or local storage
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
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 onepw requirement
  • 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.