Skip to content

Conversation

@dalisyron
Copy link

@dalisyron dalisyron commented Jan 24, 2026

Background / motivation

The Android plugin currently expects a PEM file path for certificate pinning. On Android 10+ with scoped storage, the Shadowsocks host process cannot read files from /storage/emulated/0/Download without SAF. The result is a poor UX: users must push a PEM into a world-readable location (e.g. /data/local/tmp) via adb. That breaks the “single ss:// import” workflow.

To preserve the one-step import flow while keeping security equivalent to the current leaf-cert pin, this PR adds cert-sha256 pinning (SHA-256 of the leaf certificate DER). This allows compact, link-friendly pinning without file access.

What this changes

Client (core change):

  • Adds --cert-sha256 CLI option and cert-sha256 SIP003 option.
  • Verifies the leaf certificate by SHA-256 of DER bytes (security-equivalent to current leaf PEM pin).
  • cert-sha256 takes precedence over cert if both are present.

Server (tooling):

  • Adds --print-ss-plugin helper to print cert-sha256 and a URL-encoded plugin= value suitable for ss:// links.

Docs:

  • Updates SIP003 and usage docs to describe cert-sha256 and precedence rules.

Example usage (redacted)

# On the server, print the cert hash + plugin param
slipstream-server \
  --cert /path/to/cert.pem \
  --key /path/to/key.pem \
  --domain example.com \
  --print-ss-plugin

Output includes:

cert-sha256=<HEX>
plugin-opts=domain=example.com;cert-sha256=<HEX>
plugin=slipstream%3Bdomain%3Dexample.com%3Bcert-sha256%3D<HEX>

Then use the plugin= value inside an ss:// link.

Related

Testing

  • cargo fmt
  • cargo test -p slipstream-dns
  • cargo test

@Mygod Mygod added the wontfix This will not be worked on label Jan 24, 2026
@Mygod
Copy link
Owner

Mygod commented Jan 24, 2026

@Mygod Mygod closed this Jan 24, 2026
@dalisyron
Copy link
Author

@Mygod

Thanks for the feedback. Could you clarify what makes certRaw the better solution in your view?

I agree that certRaw fixes the Android file‑path/SAF issue. But my motivation for cert-sha256 is also link usability: embedding the full PEM (~1-2KB) makes ss:// links very long and QR codes large/fragile, which makes sharing the configs hard. If the alternative is distributing a separate PEM file (as in v2ray), that’s also an extra user hurdle. With cert-sha256, the link only grows by 64 hex chars, keeping one‑step imports practical.

Security‑wise it’s equivalent to leaf pinning (preimage on SHA‑256 is infeasible). I understand the value of ecosystem consistency, so I’m happy to support both: certRaw for the existing pattern and cert-sha256 as an optional compact form.

Let me know what you prefer.

@Mygod
Copy link
Owner

Mygod commented Jan 25, 2026

If you are already using Shadowsocks then you don't really need certificate pinning because Shadowsocks already handles the authentication. Certificate pinning just provides extra insurance when Shadowsocks authentication is broken, e.g. if the pre-shared key or the Shadowsocks protocol itself is compromised. In your use case, I would honestly just skip validating certificate on client for QR codes, and only pass cert over config json or other means if the user wishes to opt in.

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

Labels

wontfix This will not be worked on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants