Newer
Older
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
# Lightweight Design: A "Read-Only" Tahoe-LAFS/PrivateStorage mobile application
_The goal here is to do the minimum amount of design we can get away with while still making a quality product. Think of this as a tool to help define the problem, analyze solutions and share results. Feel free to skip sections that you don’t think are relevant (but say that you are doing so). Delete the bits in italics._
**Contacts**: Chris
**Date**: 2022-08-11
_Short description of feature. Consider clarifying by describing what it is not._
A standalone mobile application for Android which allows users to view files stored previously by the user's PrivateStorageDesktop or Gridsync client without the need to depend on an intermediate Tahoe-LAFS client node (e.g., a tahoe instance hosted on another desktop computer that serves as a "proxy" between the local mobile device and the remote storage grid) for connectivity or continued access.
**Meetings**
_Sync + Async meeting November 21_
_Decision_: Sharing with another device should be per-folder.
_Decision_: Pair a device with multiple folders from the same desktop.
**Rationale**
_Why are we doing this now? What value does this give our users? Which users?_
We have an existing contractual obligation with DRL to deliver a "working Tahoe-LAFS mobile application" by June 30th of 2023. In addition, given the rising prevalence of mobile computing, it is in PrivateStorage's business interests to enable paying customers to access some form of the PrivateStorage service via a mobile device. We collectively recognize that enabling users to _browse and view existing files that have been previously stored on a Tahoe-LAFS storage grid_ (of which PrivateStorage is one example) constitutes a desirable goal for all parties involved -- namely DRL, PrivateStorage, and end-users/customers -- even if the functionality described herein differs in kind from the features currently available on the desktop application; providing to users the ability to read files from a Tahoe-LAFS storage grid is an early -- but not a final or complete -- step towards providing a meaningful mobile experience for Tahoe-LAFS users.
**Definitions**
"Read-Only" ("RO"): the ability to view -- but not modify -- the contents of a directory and the files within it
"Read-Write" ("RW"): the ability to view and modify the contents of a directory and the files within it
"Remote": a file or resource stored on a Tahoe-LAFS storage grid
"Local": a file or resource stored on the end user's device
Rootcap: a Tahoe-LAFS directory capability typically managed by Gridsync/PrivateStorageDeskop that contains links to any/all other capabilities that the user generally cares about: by traversing all of the links beneath a rootcap, one can traverse (i.e., read the contents of) all of that given user's magic-folders.
**User stories**
_Have as many as you like. Group user stories together into meaningfully deliverable units._
As an on-the-go user of PrivateStorage, I want to be able to use my phone to view the content of files I have stored on the PrivateStorage grid so I can benefit from the information without having to bring another desktop device around with me [Jean-Paul, Phillip, Florian, Chris]
[meejah] "As a PrivateStorage subscriber I want an application that can browse and download specific files contained in one or more magic-folders I have access to so I can still make use of the service in storage-space or bandwidth constrained circumstances".
As a PrivateStorage user with both a desktop and a mobile device, I want a quick and easy way to add/join my desktop folders on my mobile device so that I don't have to manually enter or copy between my devices various pieces of configuration data (such as storage fURLs/nURLs) or secrets (such as capabilities) using a mobile keyboard (that is tiny/unwieldy, designed for natural language input, etc.).
As a desktop application user I want to be reminded what devices may have read access to each of my magic-folders so that I can make informed decisions about the files I place in them. [Jean-Paul]
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
[Nov 21 meeting] As a User being invited to a Folder, I want to see a useful error-message if my client is using a different Grid than the inviter
## Constraints and requirements
**Must**
_What things will make the project a failure if not done?_
Require network access to only the grid's storage servers (i.e., do not depend on a "proxy" Tahoe-LAFS client node)
Include a workflow for pairing/inviting/joining a mobile device to participate in read-only access to an existing magic-folder
Enable users to browse (i.e., read) the contents of currently-accessible magic-folder directories (e.g., by presenting the directory contents of a given magic-folder "snapshot" in a list-view or other equivalent set of graphical widgets that would allow users to traverse the directory tree represented within the application and identify the names of the files contained in a given (sub)directory)
Enable users to view individual files within a currently-accessible magic-folder (i.e., by downloading them from the remote storage grid to a temporary local location and opening them using an application appropriate to the file-type)
Be available in a platform-stardard application format (".apk" or ".aab") for download via GitHub ("One mobile application released open source on GitHub" according to "DRL docs")
Be completed by June 30th 2023
**Nice to have**
_What things will improve the project if done but which are not fatal if not done?_
Include a workflow for unpairing/ejecting/removing a mobile device from participation in future changes to a magic-folder to which it has access
Richer file metadata: filesize information, last-modified time information, per-MIME-type icons, per-file thumbnails
Be available on Android "app stores" -- PlayStore, F-Droid
Be more secure than the first magic-folder revision ("tahoe magic-folder *"). That version did pairing by forcing the user to copy/paste a code that contained long-term Capabilities. One failure mode gave a passive observer the perpetual ability to view (and impersonate) the "invited" device. One way to state this requirement is that any communication channel to distribute Capabilities or other secrets should be at least as robust as Winden or Destiny (which means both ends learn if a MitM attack happened and if that didn't happen all communications are secure).
**Must not**
_What things will make the project a failure if done?_
The mobile application must not depend on the availability of an intermediate Tahoe-LAFS node (i.e., a tahoe instance running on a computer that is not the user's local device) for connectivity to storage-grid and/or the ability to view remote directories/files
**Out of scope**
_What things may or may not be nice but which belong in a separate project?_
- Read-Write; the ability to upload files from the local (mobile) device to the remote storage grid
- Continuous remote-to-local directory-synchronization
- Continuous local-to-remote directory-synchronization
- "Sharing" (which is vague but which might include adding/inviting other devices to magic-folders, sending files, etc. from the mobille device)
## Success
**How will we know when we are done?**
**How will we measure how well we have done?**
_It might be a good idea to stop at this point & get feedback, to make sure you’re solving the right problem._
## Alternatives considered
_What we’ve considered. What trade-offs are involved with each choice. Why we’ve chosen the one we did._
**"Remote control"**: We have previously considered -- and implemented -- a "remote control" architecture whereby the mobile application serves as a "light" client that sends tahoe WAPI requests to an tahoe instance that is running elsewhere (e.g., on a desktop computer on the local network managed by Gridsync). With such a design, the mobile application depends entirely on the availability of the external tahoe instance for all basic operations (e.g., browsing a remote directory, downloading files, uploading files), however, this is undesirable for the general reason that it requires that end users take additonal user-specific steps to both a) ensure continuous access to the external tahoe instance (e.g., by opening up port-forwards on a local router/firewall or using other NAT-traversal techniques) and b) protect the external tahoe instance from unauthorized access -- both of which constitute additional friction and/or require additional actions on behalf of users that may not be desirable (or even possible). In addition, such a design also (arguably) violates Tahoe-LAFS' original design principles (i.e., of not depending on other parties/systems to preserve the confidentiality, integrity, and availability of data).
**The desktop/Gridsync clone**: It may be desirable for a "Tahoe-LAFS mobile" application to possess the same (or roughly equivalent) functionality present on existing desktop-based Tahoe-LAFS applications -- namely, Gridsync -- such as the ability to create or restore from a Recovery Key, receive native notifications, the ability to launch automatically upon login, bi-directional directory-synchronization (via Magic-Folder), and so on. Such efforts would naturally demand additional design and development work that may not be feasible given our current deadline (and our lack of mobile development experience). In addition, it is questionable whether some desktop-features may be appropriate for mobile in the first place, given some of the foundational differences between the platforms:
- Storage: on baseline desktop systems, storage is typically cheap and readily available in comparison to mobile (where storage considerably more scarce and expensive). A baseline Macbook Air, for example, defaults with 256 GB of storage (with options up to 2 TB) whereas an iPhone 14 defaults with 128 GB of storage (with options only up to 512 GB). External storage options (e.g., in the form of additional USB drives) are also much cheaper and more commonly available on desktop systems, while mobile equivalents (in the form of expandable storage via SD cards) are significantly more expensive per-GB and, on some mobile platforms not available at all. In short, storage on mobile devices is a scarce resource; accordingly, it may be less desirable for users to mirror the entire contents of a magic-folder on a mobile device (in comparison to desktop)
- Network data: In many (most?) nations, mobile network data is billed on a per-usage basis and is often prohibitively expensive. I (Chris), for example, currently pay ~$80/month for 12 GB(!) of mobile data transfer, whereas my home (cable) connection has no limit and costs approximately the same amount per month. Accordingly, mobile users may not want to incur the cost of continuous bidirectional directory-synchronization -- or at least, they would surely want the option to disable it on certain networks (which increases the scope of development)
- Power consumption: Unless charging, mobile devices typically run off battery power, while desktop devices commonly -- but not always (e.g., in the case of laptops) -- run directly off a dedicated power source. Minimizing battery-drain is generally of high priority for mobile users/platforms such that background processes are heavily restricted (on iOS) or otherwise require special permissions (on Android). Running one or more background processes (e.g., a `tahoe` and `magic-folder` daemon that frequently intercommunicate with each other -- as is the case presently on desktop) would consume a non-trivial amount of power that could lead to increased user-frustration and/or the desire to terminate or uninstall the application. Ideally, we should strive to avoid situations in which the user might develop an antagonistic relationship with our software and/or otherwise need to devote additional time/effort to managing the resources that it consumes.
In sum, a large part of the appeal of "cloud" computing for mobile users lies in the ability to "outsource" the consumption of various resources to other remote systems that are not the local device, accessing the fruits of those resources (e.g., files, in the case of cloud storage) only as-needed or on-demand. A mobile application that strives to emulate a desktop experience -- and/or which fails to take into account and carefully manage the differing constraints of the underlying platform -- runs contrary to the most common user-expectations pertaining to mobile computing.
(For continuous directory-synchronization on Android that is free (both as in "speech" -- and as in "beer") and already available, see [Syncthing](https://syncthing.net).)
# Detailed design
_Focus on external and internal interfaces, how externally-triggered system events (e.g. sudden reboot; network congestion) will affect the system, scalability and performance._
## Device linking protocol overview
Below is described a protocol for inviting a "read-only" device to an existing magic-folder.
"Existing magic-folder" implies that some other device (i.e. Desktop Private Storage) has created such a folder, and is the administrator of it.
"Read-only" means that there is no support for handling or spending ZKAPs, which means no support for writing to or creating any mutables.
We currently assume both devices already have access to the same Grid.
How they obtained such access or configuration is outside the scope of this protocol.
The protocol has two parts: establishing a communication channel, and actually joining folders.
We separate this explicitly because we expect that future revisions will add more messages that can re-use the existing communication channel.
## Part One: Establish Communications
To establish a communication channel, we use Magic Wormhole.
The exact functioning of Magic Wormhole is beyond the scope of this document.
We do _not_ use the "Transit" portion of Magic Wormhole: all communications are via the mailbox only.
1. The Desktop device allocates a Wormhole code
- this means the Desktop is connected to the Wormhole mailbox server, has an allocated mailbox, and has a user-friendly code ready to present to the user
2. Transcribe the code to the mobile device
- (this could simply be typed in by the user -- simple to implement: first cut?)
- the code is encoded in a QR code using a variation of a "wormhole URI"
- "Wormhole URIs" are currently specified for file-transfer: https://github.com/magic-wormhole/magic-wormhole-protocols/blob/main/uri-scheme.md
- our scheme doesn't use file-transfer (it is a custom protocol) so we need a different scheme (likely with some overlap to the above)
- something like `ps-pair:4-hurricane-equipment` with defaults for AppID (`private.storage/magic-folder/invites`), version (`0`), and rendezvous (`mailbox.mw.leastauthority.com`)
- that is, the QR code encodes the bytes: `ps-pair:4-hurricane-equipment`
- we _could_ include query-type arguments for the other parts (similar to file-transfer) if we need
- (our application could register as the handler for `ps-pair:` URIs).
- the read-only application decodes the QR code (or is handed it via the "Intent" API if the above point is followed)
3. Use the code to establish communications
- whether it was typed or came from a QR code, we now have the code and can complete the Wormhole protocol
- the read-only application now has access to the same mailbox as the desktop with the same shared secret
- they know this because a magic-wormhole `versions` message has been exchanged (serving as key-verification). See [Magic Wormhole documentation](https://github.com/magic-wormhole/magic-wormhole/blob/master/docs/client-protocol.md) for more details.
- TODO: do we put something about this particular protocol in versions?
Once communications are established, we're ready to send and receive Private Storage specific messages via the mailbox.
All such messages are JSON encoded.
All such messages include a `kind` field.
Although we only specifiy a single sort of message here, there will be more messages in the future.
The inviting device sends an "invite" message to the read-only device::
"folder-name": "arbitrary string",
"collective-dmd": "<read-only Directory URI>",
"participant-name": "arbitrary string",
The "`folder-name`" is an arbitrary string which is what the admin device calls this folder;
it may be re-used by the read-only device or ignored (e.g. the UI may allow the read-only application to call this folder whatever they want).
The "`collective-dmd`" is a read-only Tahoe-LAFS directory URI and represents all participants in the magic-folder.
It could serve as a unique identifier for the magic-folder.
The administrating device decides all participant names, and tells the read-only device what its name will be in "`participant-name`" (i.e. a sub-directory by this name will ultimately appear in the Collective).
This name is arbitrary (i.e. the human using the administration device types it in).
For these kinds of invites, "`read-only`" will always by `True`.
A read-only device receiving an invite with "`read-only`" set to `False` SHOULD reply with an error.
Upon receipt of such an invite, the read-only device MUST respond with a reply message.
This message can be affirmative or not -- for example, a UI may ask the read-only device user for confirmation.
An affirmative reply is essentially empty and looks like::
A rejection reply says why we are rejecting the invite and looks like::
If the inviting device receives a rejection message, it MUST NOT add the participant to the Collective.
When receiving an affirmative reply, the inviting device adds a read-only, immutable, empty directory to the Collective under the given name.
This entry indicates to all users of the Collective that a given device has read-only access.
This concludes the protocol and both sides close their mailboxes.
**Future enhancement**: a participant could be invited to multiple folders by doing multiple rounds of the above communication. This then needs a way to associate replies to requests (e.g. unique IDs, or enforced sequential answers, or some other technique)
**Future enhancement**: either side could perform multiple rounds of folder-invites. (Similar to above this might require IDs or other techniques to tie replies to requests).
**Future enhancement**: further kinds of messages could exchange other kinds of information between devices (e.g. sending ZKAPs or Grid configuration)
**Future enhancement**: the communication channel could become longer-term by using the proposed "Seeds" feature of magic-wormhole (or a future message type over the wormhole could exchange capabilities to perform such communication over the Grid).
## Rejected Ideas
- **Rejected idea**: have the read-only device reply with a "pre-canned" LIT capability.
This doesn't have any excess authority or security implications, but doesn't fit as well with the notion that "the administation device decides".
Currently, that device has authority over the list of participants and what they are called because it retains the sole write-capability to the Collective.
It thus makes sense for it to also decide which devices are read-only and which can write data.
(Note that future revisions may distribute such authority further)
- **Rejected idea**: produce a "devicecap" or "rootcap" _for_ the read-only device. This leads to excess authority on the inviting device (it could retain the write-capabilities and impersonate the read-only device forever).
**Data integrity**
**Security**
- Excess authority: even though the read-only device cannot perform changes to the Grid, this design avoids leaving excess authority with the inviting device.
- QR Code interception: if a magic-wormhole code is intercepted, an adversary may race the legitimate participant in establishing the wormhole connection. If successful, the adversary will learn the read-only Collective capability and may forever read all contents of the folder. The legitimate participant will learn that they lost, because their wormhole connection will fail with an error.
It is possible to mitigate this by using the "verifier" approach for Magic Wormhole connections.
This would mean pausing after the wormhole is established and before sending any folder invites so that the two participants can confirm a verifier string and thus be assured that they have the same mailbox and shared secret.
- Wormhole interception: we believe it is computationally infeasible to brute-force or otherwise gain access to the shared secret necessary to perform wormhole communications (as per Magic Wormhole security arguments). An advesary would have to gain access to one of the participant devices and extract the key from there. They could give themselves more time by DoS-ing the network of the other participant, however the time-window is still small (between when the wormhole is established and the end of communications). After both sides close their wormholes and erase their secrets it is impossible to compromise the communications (even if the adversary has access to the mailbox server) without brute-forcing the key.
**Threat**: visual collection by passive observation
QR codes are designed to make encoded information highly legible to machines and contain error-correction properties intened to improve legibility in situations where the image itself might become obscured (e.g., due to low lighting, partial covering, poor viewing angles, etc.). As a consequence of this, it is easy -- by design -- for passive observers (such as a surveillance camera in the vicinity of the user) to read and interpret the information encoded in a QR code. This naturally makes it possible for systems and actors other than the user's intended mobile device to intercept any information transmitted between devices using this medium.
**Threat**: unauthorized access to shared folder.
All devices with access to a shared folder contain (at least) a Tahoe read-capability allowing future updates to be read. Anyone gaining knowledge of this capability can forever read existing and future updates to the shared folder. Currently, this capability is stored in the configuration area of GridSync (in Tahoe's "private/" folder).
In this design, we anticipate communicating (at least) a read-capability to the shared folder to an additional device. The impact of revealing this secret is high: a user can forever read updates, unbeknowst to anyone else. Guarding against accidental disclosure of this should be high priority.
## Backwards compatibility
## Performance and scalability
## Further reading
_Links to related things. Other designs, tickets, epics, mailing list threads, etc._
DRL Requirements: https://cryptpad.fr/pad/#/2/pad/edit/f9aPupTgCK5sWn2uUBotr8B8/
Phillip's "PS-Mobile-User-Stories-Notes/Draft": https://docs.google.com/document/d/1zmjLsELTQDLvijLY-CKYurL0gwS5Bq1ByMhwPl4PXoY/edit
Old tahoe-mobile notes (LA Google login required): https://docs.google.com/document/d/1xDC02XUUlDpIlfCFUPWtwVh9h1epktdSN8-bykDSeNI/edit#
Old UI design (on Figma; deprecated): https://www.figma.com/file/OUUP0J5fCp1ckHBd84eksx/Tahoe-LAFS-Android-(rough-sketch)
Old UI design/prototype (on Penpot): https://penpot.gridsync.io/#/view/2f5ce419-fdfd-80cc-8001-cb58b83d84cc?page-id=2f5ce419-fdfd-80cc-8001-cb58b83d84cd§ion=interactions&index=4&share-id=aa55a301-cee6-8144-8001-d967ebbe1cc3
Current/old implementation of the above design: https://github.com/LeastAuthority/tahoe-lafs-android-app
Gridsync branch with (outdated/old-magic-folder) mobile pairing functionality: https://github.com/gridsync/gridsync/tree/mobile-gateway-bridge.3
## Open Questions