shadowsocks / shadowsocks/shadowsocks-org

Secure single-port multi-user authentication

Open
#54 46 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
HTML
Stars
1k
Forks
694
PR merge metrics
No merged PRs in 30d

Description

Summary

Current commercial deployments of Shadowsocks suffer from a social-engineering weakness that any client knows the Symmetric Pre-Shared Key (SPSK) and can use it to MitM attack other clients of the same server.

To counter this weakness, SPSK must be abandoned in favor of asymmetric private/public key pairs. The server's private key must be kept secret at all times. Clients only know the server's public key, and must derive a per-session subkey to talk to the server. No clients can pretend to be the server because it does not have the server's private key.

An additional benefit of using asymmetric key pairs is that multiple users can share the same port securely without revealing their own client identifiers.

Update

Please see https://github.com/shadowsocks/shadowsocks-org/issues/54#issuecomment-589549957 for the latest proposal. The following section is the original proposal without forward secrecy protection.

Details (OBSOLETED)

  1. The server randomly generates a pair of keys on Curve25519: a private key sk that must be kept secret, and a public key pk that is distributed to all clients beforehand.

    sk, pk = curve25519_keypair(random_seed)

  2. Each time a client wants to talk to the server, it randomly generates another pair of keys on Curve25519: a private key sk' that must be kept secret, and a public key pk' to be sent to the server.

    sk', pk' = curve25519_keypair(random_seed)

  3. The client computes the shared secret with the server using x25519 ECDH function:

    shared_secret = x25519(sk', pk)

  4. The client derives the per-session subkey using HKDF_SHA256:

    subkey = HKDF_SHA256(shared_secret || pk' || pk)

  5. The client encrypts payload using the subkey and sends the encrypted data to server.

  6. The server receives the client's public key pk' and computes the shared secret using x25519 ECDH function:

    shared_secret = x25519(sk, pk')

  7. The server derives the per-session subkey using HKDF_SHA256:

    subkey = HKDF_SHA256(shared_secret || pk' || pk)

  8. The server uses the subkey to decrypt the encrypted payload.

Note that x25519 ECDH function ensures x25519(sk, pk') == x25519(sk', pk).

To implement secure multiuser support, the client can include its Client Authentication (e.g. username/password) in the payload for the server to verify against a database. Detailed format will be discussed separately.

Contributor guide

No contributing guide indexed for this repository

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

Read the latest proposal in the linked issue comment first; the detailed section in this issue is explicitly obsolete. No implementation files, tests, or entry points are named, so the next step is to locate the protocol and authentication code before defining the implementation scope. Done would require an agreed secure multi-user authentication design and corresponding implementation and tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
cryptography
Domain
authentication, backend-api-design, cryptography, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.