Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support sharing passwords #79

Open
palant opened this issue Feb 17, 2018 · 3 comments
Open

Support sharing passwords #79

palant opened this issue Feb 17, 2018 · 3 comments

Comments

@palant
Copy link
Owner

palant commented Feb 17, 2018

Most password managers use RSA to share passwords. This approach has a critical weakness: you have no way of knowing that the public key you share the passwords with belongs to the right person. Most of the time this boils down to trusting the server, not something we want to have here.

I see a better way however:

  • When you create a new share for one or multiple passwords, PfP should generate a "share name" (9 random bytes).
  • In the human-readable presentation, the "share name" gets one byte added (Pearson hash, used to validate input) and encoded as 16 Base32 characters: ABCD-EFGH-JKLM-NPQR
  • PfP uses "share name" like a master password, deriving an encryption key from it (fixed salt, which should be fine because preimage attacks against 72 bit passwords aren't feasible).
  • PfP then generates the shared passwords, encrypts the values with this encryption key and uploads them to a server, advising this server to provide the data for public download under a predictable URL, probably determined by the SHA-256 hash of the encryption key.
  • The human-readable presentation of the "share name" is shown to the user so that they can share it with somebody else via a secure channel:
    • In person
    • Over phone
    • Via end-to-end encrypted private chat
    • Ideally not via email
  • In another PfP instance (not necessarily sharing the same master password), another user can enter this "share name." With it, their PfP instance will be able to both locate and decrypt the data.

Some additional considerations:

  • I considered using 5 random bytes for the "share name" without a checksum, which should still be safe with scrypt-based encryption key derivation. 9 bytes offer a larger security margin however.
  • Ideally, sharing wouldn't be a one-time thing. Instead, uploaded data would be updated whenever a shared password is changed or removed. Consequently, the PfP instance the data is shared with would check the server for updates regularly. This can go as far as "unsharing" which should remove the data from the server, in this case the other instance should remove the passwords shared with it. Unlike sync, this doesn't need to happen when passwords are locked.
  • "Unsharing" doesn't mean of course that the other user didn't create a copy of the passwords, so changing passwords is still required.
  • If updating the share fails (e.g. user offline), the error needs to be surfaced to the user somehow, and it should be possible to redo the operation later.
  • The data structure for sharing has to support both lookups by password (is this password shared?) and by share (manage passwords by share). Ideally, this should be done without much redundancy or potential for data structures to get out of sync.
  • The data structure for shared passwords needs to support the scenario where a password shared with me has the same username as one of my own passwords. So rather than site/username/revision combination being the key, we'll have site/username/revision/sharename as key.
  • Ideally, the server in question wouldn't be something PfP-specific but rather a public one. Maybe determining URL of public Dropbox files is possible with the file name (SHA-256 hash of the encryption key) and Dropbox user name. This would require entering one more piece of data (Dropbox user name) but still.
@palant
Copy link
Owner Author

palant commented Mar 9, 2018

I looked into services that could be (mis-)used for this:

  • Dropbox, Google Drive, OneDrive all allow sharing files but will generate a random link. So these can only be used in conjunction with a URL shortener service that allows setting URL such as is.gd.
  • GitHub Gists would work in theory, one would put the SHA-256 digest of the encryption key into the description to make it discoverable. Using this is awkward however:
    • GitHub account required for sharing.
    • Retrieving requires GitHub user name and will have to go through all of user's gists (no search via API).
    • All gists are publicly visible. So while the contents are encrypted, the actual fact that shares exists and their count cannot be hidden.
  • Rentry.co has exactly the required functionality. However, it is an unknown web service run but an anonymous. Even if the service owner grants permission to misuse it like this, reliability of this solution is questionable.

With the is.gd API being so simple to use (also, see their ethics commitment), the first option might be viable. Still, having to rely on two services for this seems suboptimal.

@palant
Copy link
Owner Author

palant commented Mar 9, 2018

After thinking more about this, I am leaning strongly towards combining a regular storage provider (Dropbox, Google Drive) with is.gd. This has the advantage that the same account can be used for sync and sharing. Also, while the person sharing their passwords needs to select a storage provider, the receiver only needs to type in the share name - is.gd will redirect to the proper storage provider, so it doesn't have to be known. This setup has the additional advantage of adding to the transparency, at least in case of Dropbox - the user can always verify what data is stored in their account.

Share update can happen immediately when a password is updated, this especially affects editing notes. This way unnecessary uploads can be avoided, and passwords will always be unlocked on a share update. Surfacing an error should also be easier then. In addition, when a password is transformed (meaning in particular "Generate a new password for this user name" and "Replace by PfP 2.x password" features), the default should be adding the new password to the same shares as the original one. Users should have a way to disable automatic sharing however.

I decided that sharing settings shouldn't be part of either backups or sync. The important consideration here is that sharing should always be performed by a single device, not multiple devices potentially uploading conflicting shares. Also, keeping shared passwords after they have been "unshared" should require non-trivial effort. The disadvantage is: if data is lost, sharing has to be set up from scratch, meaning in particular that all recipients have to learn the new share name.

@palant palant closed this as completed Mar 16, 2023
@palant palant reopened this Apr 26, 2023
@palant
Copy link
Owner Author

palant commented May 4, 2023

fixed salt, which should be fine because preimage attacks against 72 bit passwords aren't feasible

I might have been overly optimistic here. Fixed salt allows running this attack against all password shares simultaneously. So if in theory at some point PfP becomes wildly popular and its users create 100 million shares (yeah, like that’s gonna happen 🥲), attackers trying out all possible share names will have 100 million higher chances of hitting one that’s used. This will still take 150 years if their hardware can run 10,000 key derivation operations per second but…

From the cryptography point of view, this scheme needs a salt. It might be the name of whoever shares passwords that the receiver will have to enter in addition to the share name. Or maybe shares should have human-readable names in addition to the code.

If I am implementing this, I’m currently strongly leaning towards setting up a minimal service for it rather than relying on third parties. The share creator will be able to upload their data under a name of their choosing, and they will have the edit key required for updating the data. The receiver will only be able to download the data. This is simple enough to implement, and it doesn’t rely on third parties keeping their service alive and available to us. Never mind that their approach to privacy might be suboptimal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant