Web client for downloading files shared from encrypted Syncthing peers.
⚠ Warning: this is beta software and could expose private files when not configured properly. Make sure you understand the security implications before using this application.
Linkthing is a web application that can fetch encrypted files as stored on an untrusted (encrypted) Syncthing peer, and decrypt them client-side (in the browser). This allows sharing links to encrypted files stored on an untrusted server, allowing others to download and decrypt these files.
sequenceDiagram
participant A as Alice running Syncthing
participant UT as Untrusted server<br>running Syncthing
participant B as Bob (in a browser)
note over A: Syncthing encrypts<br>files before sending
A -->> UT: Sync encrypted files
A -->> B: Share link to encrypted file with file key
note over B: Loads Linkthing web app
UT -->> B: Fetch encrypted file blocks<br> over HTTPS
note over B: Linkthing decrypts<br/>blocks client-side
note over B: Decrypted file offered<br/> as download
Suppose Alice uses Synchting to sync her files to an untrusted peer that is always-on and well connected. Now Alice wants to use this peer to share a specific file with Bob, without giving Bob access to any of her other files, and prevent anyone but herself and Bob from accessing any of her files.
First, Alice sets up an untrusted (encrypted) Syncthing device and syncs some files to it. On the untrusted peer, the files will be stored encrypted (and using encrypted file paths).
Second, on this server, Alice starts a regular HTTPS server that provides public access to the encrypted file directory. Anyone who knows a file path, can download files from this folder, but won't be able to decrypt them unless they know the folder password set by Alice for the encrypted peer.
Finally, Alice hosts the Linkthing web application on an ordinary static file web host.
When Alice wants to send a file to Bob, she generates an external sharing link. This link contains the following things:
- The location of the Linkthing web application
- The URL at which the encrypted file can be fetched (the file path is encrypted)
- The per-file encryption key for the file Alice wants to share
Bob's browser will load the Linkthing web application, which looks like this:
Linkthing will attempt to fetch the encrypted file from the path specified in the URL, and decrypt it using the file key also contained in the app.
Linkthing URLs contain the path to the encrypted file and the individual file encryption key in the hash part of the URL. This part of the URL is readable by the Linkthing web application from the browser, but crucially not sent to the server when the URL is loaded. This means that the server hosting Linkthing will not learn the URL and file key for encrypted files.
The hash part of a URL is a query string encoded string containing the following key/value pairs:
url: URL to the encrypted file. This should be anhttps:URL.key: The individual file key, base32-encoded.
An example of a URL in this format:
https://path.to.linkthing/#url=http://path.to.blobs/2.syncthing-enc/0S/5DKML387B7I991EQMGUK7KE9BSGRV95PMHTOMMY916HGLQPBHSAEA8HRFS77G74IIE9HO&key=PUL3G0EFTVMG2M7N6HFV37EIU5AH548DV5J4BTOMMYSKONQS00KG
Linkthing is beta software and should not be used in production. A few security considerations:
- The threat model for the link sharing scheme is one where there are two trusted nodes, and an untrusted node (in i.e. a public cloud) storing files. Finally there is a trusted web host serving a static web app. The goal is to maintain file confidentiality even if the untrusted server is fully compromised.
- Syncthing files are encrypted using a per-file key, which is derived using the folder password, the full file path (including file name) and the folder ID. Because of this, anyone who learns the file path and corresponding file key will also be able to decrypt any version of the file, because it will be encrypted using the same file key.
- Because the receiver does not learn the folder password (and assuming proper use of cryptography in Syncthing), the receiver will not be able to decrypt any of the other encrypted files, even if it could retrieve these by guessing file names (as these files are encrypted using individual file keys).
This can be any old HTTP server (i.e. nginx, Apache2) running on HTTPS, serving up an encrypted folder tree.
The HTTP server serving encrypted files should support HEAD and OPTION requests, and send appropriate Access-Control-Allow-Origin headers to allow file downloads from the origin where the Linkthing app is served from. If the Linkthing app is at https://link.thing, the encrypted file server should send:
Access-Control-Allow-Origin: https://link.thingFor local testing, you can use npx http-server -- --cors.
This can be any other static file host as long as it's using HTTPS.
The Linkthing app should be served with an Content Security Policy header allowing file downloads (only) from the relevant encrypted file server. If the encrypted files are at https://encrypted.files, the header should look something like (you can configure this with e.g. .htaccess):
Content-Security-Policy: default-src 'self'; connect-src https://encrypted.filesFor local testing, use npm run dev (development server with hot reloading) or npm run build followed by npm run preview.
npm install
npm run buildnpm install
npm run devExcept when explicitly noted otherwise, the code in this repository is licensed under the Mozilla Public License 2.0. Read the license here. Contributors to this repository agree to license their contributions under this license.
The following items are explicitly not licensed under the abovementioned license. Instead all rights are reserved by the author / the respective owners:
- base32.ts: MIT License
Copyright 2024 Tommy van der Vorst
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Syncthing is a trademark of the Syncthing Foundation. Read more over at syncthing.net. This project is not endorsed by, nor affiliated with, neither Syncthing contributors nor the Syncthing Foundation.