Repository navigation
Conversation
Add `ss-local --printable-salt` / `"printable_salt": true`, disabled by default. For each outgoing TCP salt it picks a prefix length uniformly from 6-12 bytes and samples those bytes as printable ASCII (0x20-0x7e) immediately before key derivation. The salt stays 32 bytes with no framing or markers, so the wire format is unchanged and any stock server interoperates. Only chacha20-ietf-poly1305 and aes-256-gcm are accepted; other ciphers fail at startup. UDP, server responses, and AEAD-2022 are untouched. Crypto unit tests cover length distribution, empty first writes, exact framing overhead, salt-tail preservation, byte-at-a-time decryption, tampering and replay rejection. CLI tests check local-only exposure and cipher rejection via flag, config key and bad config type. interop.py gains --printable-salt and --server-bin for independent stock servers. docs/printable-salt.md records the design, entropy bound, fingerprint caveats and route-experiment procedure; docs/encoding-experiments.md and tests/experiments/ hold the Base85/lowpop85/TLS outer-transport prototypes. docs/measurements/printable-salt-2026-09-23/ archives the sanitized results of the aborted field trials. Co-Authored-By: Claude <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an opt-in, disabled-by-default client-side experiment:
ss-local --printable-salt(or"printable_salt": truein the config). For each outgoing TCP salt it picks a prefix length uniformly from 6–12 bytes and overwrites those bytes with independently sampled printable ASCII (0x20–0x7e) right before key derivation.chacha20-ietf-poly1305andaes-256-gcmare accepted; other ciphers fail at startup, including when the cipher comes from a config file. UDP salts, server responses, and AEAD-2022 are untouched. The flag is ss-local only.(32-L)*8 + L*log2(95)≥ 238.8 bits; salt uniqueness remains essential and is still enforced by the bloom filter.This is motivated by the historical six-printable-byte exemption reported in the USENIX Security '23 GFW study. It is not TLS impersonation and not a claim of censorship resistance — see the caveats in
docs/printable-salt.md. The 2026‑09‑23 field trials archived underdocs/measurements/both aborted before crossover; all recorded transfers (stock and modified) succeeded, so they show interoperability only, not an availability advantage.Changes
src/aead.c,src/crypto.h:cipher_ctx.printable_saltflag; prefix rewrite on the first non-empty TCP encrypt, beforeaead_cipher_ctx_set_key.src/local.c,src/jconf.[ch],src/common.h,src/utils.c:--printable-saltoption,printable_saltconfig key, cipher validation, Doxygen CLI snippet, help text gated onMODULE_LOCAL.completions/,doc/shadowsocks-c.md,README.md: flag documented.tests/test_crypto.c: length distribution (all seven lengths over 512 samples), empty first write, exact framing overhead, salt-tail preservation, byte-at-a-time decrypt, tampering, replay rejection — for both ciphers, enabled and disabled.tests/test_cli.py: local-only exposure; rejection via flag, config key, and non-boolean config value.tests/interop.py:--printable-saltand--server-bin(independent stock server). New CTesttest_printable_salt_interop.tests/experiments/+docs/encoding-experiments.md: Base85 / lowpop85 / verified-TLS outer-transport prototypes (research fixtures, not plugins), with codec and supervisor-cleanup tests registered in CTest.tests/printable_salt_experiment.py,tests/check_printable_pcap.py: route-experiment runner and pcap first-payload checker.Test plan
Verified locally on macOS arm64:
cmake --build build && ctest --test-dir build -LE memcheck— 39/39 passed (includes the 3 new integration tests)python3 tests/stress_test.py --bin build/bin/ --size 10— 3/3 passeduvx ruff==0.15.6 check --select E9,F63,F7,F82 tests scripts— cleanpython3 scripts/check_cli_docs.pyandpython3 -m unittest discover -s tests -p test_cli_docs.py— pass🤖 Generated with Claude Code