torquests 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. torquests-1.0.0/.github/CONTRIBUTING.md +91 -0
  2. torquests-1.0.0/.github/SECURITY.md +61 -0
  3. torquests-1.0.0/LICENSE +674 -0
  4. torquests-1.0.0/MANIFEST.in +7 -0
  5. torquests-1.0.0/NOTICE +8 -0
  6. torquests-1.0.0/PKG-INFO +183 -0
  7. torquests-1.0.0/README.md +136 -0
  8. torquests-1.0.0/examples/README.md +17 -0
  9. torquests-1.0.0/examples/fetch_clearnet.py +13 -0
  10. torquests-1.0.0/examples/fetch_onion.py +18 -0
  11. torquests-1.0.0/examples/run_socks_proxy.py +15 -0
  12. torquests-1.0.0/examples/session_and_identity.py +19 -0
  13. torquests-1.0.0/pyproject.toml +126 -0
  14. torquests-1.0.0/setup.cfg +4 -0
  15. torquests-1.0.0/src/torquests/__init__.py +98 -0
  16. torquests-1.0.0/src/torquests/__main__.py +10 -0
  17. torquests-1.0.0/src/torquests/_client/__init__.py +1 -0
  18. torquests-1.0.0/src/torquests/_client/bootstrap.py +560 -0
  19. torquests-1.0.0/src/torquests/_client/config.py +21 -0
  20. torquests-1.0.0/src/torquests/_client/torclient.py +499 -0
  21. torquests-1.0.0/src/torquests/_crypto/__init__.py +6 -0
  22. torquests-1.0.0/src/torquests/_crypto/ed25519_blind.py +115 -0
  23. torquests-1.0.0/src/torquests/_crypto/primitives.py +147 -0
  24. torquests-1.0.0/src/torquests/_dir/__init__.py +6 -0
  25. torquests-1.0.0/src/torquests/_dir/authorities.py +50 -0
  26. torquests-1.0.0/src/torquests/_dir/consensus.py +155 -0
  27. torquests-1.0.0/src/torquests/_dir/dirhttp.py +136 -0
  28. torquests-1.0.0/src/torquests/_dir/guards.py +91 -0
  29. torquests-1.0.0/src/torquests/_dir/keycerts.py +102 -0
  30. torquests-1.0.0/src/torquests/_dir/microdesc.py +28 -0
  31. torquests-1.0.0/src/torquests/_dir/models.py +126 -0
  32. torquests-1.0.0/src/torquests/_dir/parsers.py +365 -0
  33. torquests-1.0.0/src/torquests/_dir/pathselect.py +238 -0
  34. torquests-1.0.0/src/torquests/_http/__init__.py +5 -0
  35. torquests-1.0.0/src/torquests/_http/connection.py +63 -0
  36. torquests-1.0.0/src/torquests/_http/response.py +76 -0
  37. torquests-1.0.0/src/torquests/_http/streamsocket.py +109 -0
  38. torquests-1.0.0/src/torquests/_http/tlssocket.py +109 -0
  39. torquests-1.0.0/src/torquests/_net/__init__.py +5 -0
  40. torquests-1.0.0/src/torquests/_net/channel.py +144 -0
  41. torquests-1.0.0/src/torquests/_net/circuit.py +368 -0
  42. torquests-1.0.0/src/torquests/_net/flowcontrol.py +115 -0
  43. torquests-1.0.0/src/torquests/_net/hop.py +40 -0
  44. torquests-1.0.0/src/torquests/_net/link.py +133 -0
  45. torquests-1.0.0/src/torquests/_net/sink.py +25 -0
  46. torquests-1.0.0/src/torquests/_net/stream.py +176 -0
  47. torquests-1.0.0/src/torquests/_net/transport.py +135 -0
  48. torquests-1.0.0/src/torquests/_onion/__init__.py +1 -0
  49. torquests-1.0.0/src/torquests/_onion/address.py +105 -0
  50. torquests-1.0.0/src/torquests/_onion/descriptor.py +538 -0
  51. torquests-1.0.0/src/torquests/_onion/hsdir.py +160 -0
  52. torquests-1.0.0/src/torquests/_onion/rendezvous.py +164 -0
  53. torquests-1.0.0/src/torquests/_proto/__init__.py +6 -0
  54. torquests-1.0.0/src/torquests/_proto/cells.py +229 -0
  55. torquests-1.0.0/src/torquests/_proto/certs.py +106 -0
  56. torquests-1.0.0/src/torquests/_proto/constants.py +132 -0
  57. torquests-1.0.0/src/torquests/_proto/handshake/__init__.py +11 -0
  58. torquests-1.0.0/src/torquests/_proto/handshake/hs_ntor.py +131 -0
  59. torquests-1.0.0/src/torquests/_proto/handshake/ntor.py +89 -0
  60. torquests-1.0.0/src/torquests/_proto/linkspec.py +99 -0
  61. torquests-1.0.0/src/torquests/_proto/relay.py +214 -0
  62. torquests-1.0.0/src/torquests/_proto/relay_crypto.py +110 -0
  63. torquests-1.0.0/src/torquests/adapter.py +176 -0
  64. torquests-1.0.0/src/torquests/api.py +90 -0
  65. torquests-1.0.0/src/torquests/cli.py +105 -0
  66. torquests-1.0.0/src/torquests/client.py +17 -0
  67. torquests-1.0.0/src/torquests/exceptions.py +184 -0
  68. torquests-1.0.0/src/torquests/py.typed +0 -0
  69. torquests-1.0.0/src/torquests/sessions.py +166 -0
  70. torquests-1.0.0/src/torquests/socks.py +205 -0
  71. torquests-1.0.0/src/torquests/stealth.py +245 -0
  72. torquests-1.0.0/src/torquests.egg-info/SOURCES.txt +102 -0
  73. torquests-1.0.0/tests/__init__.py +0 -0
  74. torquests-1.0.0/tests/conftest.py +53 -0
  75. torquests-1.0.0/tests/crypto_helpers.py +20 -0
  76. torquests-1.0.0/tests/dir_fixtures.py +350 -0
  77. torquests-1.0.0/tests/fakes.py +418 -0
  78. torquests-1.0.0/tests/onion_fixtures.py +389 -0
  79. torquests-1.0.0/tests/onion_service_fake.py +92 -0
  80. torquests-1.0.0/tests/test_adapter.py +287 -0
  81. torquests-1.0.0/tests/test_cli.py +75 -0
  82. torquests-1.0.0/tests/test_crypto_helpers.py +14 -0
  83. torquests-1.0.0/tests/test_crypto_primitives.py +135 -0
  84. torquests-1.0.0/tests/test_dir.py +785 -0
  85. torquests-1.0.0/tests/test_dir_tunnel.py +428 -0
  86. torquests-1.0.0/tests/test_ed25519_blind.py +105 -0
  87. torquests-1.0.0/tests/test_exceptions.py +45 -0
  88. torquests-1.0.0/tests/test_fail_loud.py +367 -0
  89. torquests-1.0.0/tests/test_handshake.py +126 -0
  90. torquests-1.0.0/tests/test_live_integration.py +199 -0
  91. torquests-1.0.0/tests/test_net_channel.py +146 -0
  92. torquests-1.0.0/tests/test_net_circuit.py +235 -0
  93. torquests-1.0.0/tests/test_net_link.py +79 -0
  94. torquests-1.0.0/tests/test_net_stream.py +141 -0
  95. torquests-1.0.0/tests/test_onion_address.py +106 -0
  96. torquests-1.0.0/tests/test_onion_v3.py +386 -0
  97. torquests-1.0.0/tests/test_proto_wire.py +344 -0
  98. torquests-1.0.0/tests/test_public_api.py +52 -0
  99. torquests-1.0.0/tests/test_relay_crypto.py +132 -0
  100. torquests-1.0.0/tests/test_rendezvous.py +188 -0
  101. torquests-1.0.0/tests/test_sessions.py +167 -0
  102. torquests-1.0.0/tests/test_socks.py +129 -0
  103. torquests-1.0.0/tests/test_stealth_integration.py +45 -0
  104. torquests-1.0.0/tests/test_torclient.py +109 -0
  105. torquests-1.0.0/tests/vectors/hs_ntor.json +19 -0
@@ -0,0 +1,91 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in `torquests`. This document covers the development
4
+ setup and the conventions the project holds to.
5
+
6
+ ## Development setup
7
+
8
+ The project uses [uv](https://docs.astral.sh/uv/) for environments and
9
+ [ruff](https://docs.astral.sh/ruff/) + [mypy](https://mypy-lang.org/) + pytest for
10
+ quality gates.
11
+
12
+ ```bash
13
+ git clone https://github.com/SafwanLjd/torquests
14
+ cd torquests
15
+ uv venv
16
+ uv pip install -e ".[dev]"
17
+ pre-commit install
18
+ ```
19
+
20
+ Everyday commands run the tools installed above through `uv run`:
21
+
22
+ ```bash
23
+ # lint, type-check, and test -- exactly what CI runs
24
+ uv run ruff check src tests
25
+ uv run ruff format --check src tests
26
+ uv run mypy src
27
+ uv run pytest
28
+
29
+ # auto-fix lint and format in place
30
+ uv run ruff check --fix src tests && uv run ruff format src tests
31
+
32
+ # live-network suite (needs a reachable Tor network)
33
+ uv run pytest --run-integration -m integration
34
+ ```
35
+
36
+ ## Test-driven, offline-first
37
+
38
+ This is a network library, so its tests must not touch the network. The unit suite
39
+ runs with sockets disabled (`--disable-socket`); a layer that seems to need the
40
+ network to test needs a fake transport instead. The `FakeRelayTransport` in the test
41
+ suite performs the link handshake and the server halves of the ntor and hs-ntor
42
+ handshakes in process, so circuits, streams, the directory system, and the onion
43
+ rendezvous flow are all exercised without a live relay.
44
+
45
+ Protocol code is validated against gold vectors and generated fixtures, not
46
+ against a running Tor: the official hs-ntor test vectors live in
47
+ `tests/vectors/hs_ntor.json`, the ed25519 key-blinding regression vector is
48
+ inline in `tests/test_ed25519_blind.py`, and the consensus/descriptor fixtures
49
+ are generated by `tests/dir_fixtures.py` and `tests/onion_fixtures.py`.
50
+
51
+ Write the failing test first, then the smallest code that passes it, then refactor.
52
+ Do not open a pull request on a red build.
53
+
54
+ Live-network checks are marked `@pytest.mark.integration` and are skipped unless you
55
+ pass `--run-integration` (`uv run pytest --run-integration -m integration`). They need
56
+ a reachable Tor network.
57
+
58
+ ## Style and scope
59
+
60
+ - Target Python 3.10+ and modern typing. Every public function is typed and
61
+ documented.
62
+ - Match the surrounding code. `ruff` and `mypy --strict` are authoritative; if they
63
+ pass and the tests pass, the style is right.
64
+ - Errors fail loud: no bare `except`, no fabricated fallbacks, no silently-truncated
65
+ results. Tor-specific errors subclass the matching `requests` exception.
66
+ - Verify protocol details against the Tor specifications and library behavior
67
+ against the library's own documentation. Cite the source in the code or the pull
68
+ request when the detail is non-obvious.
69
+
70
+ ## Commits and pull requests
71
+
72
+ Keep commits small and focused. Subjects follow
73
+ [Conventional Commits](https://www.conventionalcommits.org): a
74
+ `type(scope): summary` line in the imperative mood, where `type` is one of `feat`,
75
+ `fix`, `docs`, `test`, `refactor`, `perf`, `build`, `ci`, or `chore`. History reads
76
+ as an intentional story, so squash fixups before opening a pull request.
77
+
78
+ Run `pre-commit install` once (see the setup above). On every commit the hooks run
79
+ `ruff` (lint and format) and a set of file-hygiene checks (trailing whitespace,
80
+ end-of-file, YAML and TOML validity, large files); a Conventional Commits check runs
81
+ on the commit message. Describe what changed and why in the pull
82
+ request, and note the specification section or vector a protocol change rests on. CI
83
+ runs lint, type-check, and the offline suite across Python 3.10 to 3.14, and all must
84
+ pass.
85
+
86
+ ## Reporting security issues
87
+
88
+ Because this library is used for privacy, please report suspected anonymity or
89
+ cryptographic defects through a private GitHub Security Advisory (see
90
+ [SECURITY.md](SECURITY.md)) rather than a public issue, so a fix can land before the
91
+ details are public.
@@ -0,0 +1,61 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ Report suspected vulnerabilities privately. Do not open a public issue for a
6
+ security problem, and do not disclose the details publicly until a fix has shipped.
7
+
8
+ Report through **GitHub Security Advisories**: open a draft advisory at
9
+ https://github.com/SafwanLjd/torquests/security/advisories/new.
10
+
11
+ Please include the affected version, a description of the issue, and, where you can,
12
+ a minimal reproduction. This project treats anonymity and cryptographic defects as
13
+ security issues, not ordinary bugs, so report those through the same private channels.
14
+
15
+ Expect an acknowledgement within a few days. We will keep you informed while a fix
16
+ is prepared and will credit you in the advisory unless you ask otherwise. We welcome
17
+ good-faith research and will not pursue reporters who follow this policy.
18
+
19
+ ## Supported versions
20
+
21
+ Only the latest published release receives security fixes. There are no long-term
22
+ support branches.
23
+
24
+ | Version | Supported |
25
+ | ------- | --------- |
26
+ | Latest release | Yes |
27
+ | Everything older | No |
28
+
29
+ ## Anonymity limitations
30
+
31
+ torquests anonymizes the **transport**, not the application layer. It routes your
32
+ connection through Tor circuits and reaches v3 onion services directly, but it does
33
+ nothing to make the traffic it carries look like a browser's.
34
+
35
+ Understand these limits before relying on the library for anonymity:
36
+
37
+ - **The client is fingerprintable as non-browser Python.** torquests uses the
38
+ standard library `ssl` module for TLS and `http.client` for HTTP/1.1. Neither can
39
+ reproduce Tor Browser's TLS ClientHello (the cipher, extension, and curve ordering
40
+ that JA3/JA4 hash) or its HTTP/2 frame and header behaviour. A destination server
41
+ or a malicious exit relay can therefore fingerprint the client as a Python Tor
42
+ client rather than Tor Browser, and can distinguish it from the Tor Browser crowd.
43
+ - **No application-layer or browser fingerprinting defenses.** The library does not
44
+ address JavaScript execution, canvas or font fingerprinting, cookies, referrers,
45
+ redirect chains, or any of the browser-level signals that deanonymize users. What
46
+ your code sends in headers, request timing, and payloads is your responsibility.
47
+ - **No traffic-analysis or timing-correlation protection beyond what Tor circuits
48
+ provide.** A global adversary able to observe both ends of a circuit is outside the
49
+ threat model, as it is for Tor generally.
50
+ - **Entry guards are not persisted.** To leave no on-disk trace, the client draws a
51
+ fresh guard set each process rather than pinning guards across runs as Tor does, which
52
+ trades reduced forensic residue for more entry-guard exposure over time.
53
+ - **No warranty.** Do not use it where a deanonymization would put someone at risk
54
+ without independent review.
55
+
56
+ To blend into the Tor Browser user base on the wire, enable **stealth mode** (the
57
+ `torquests[stealth]` extra), which routes through curl_cffi to present a real Tor
58
+ Browser TLS ClientHello and HTTP/2 fingerprint over Tor. For the full browser
59
+ threat model (JavaScript, canvas and font fingerprinting, and the rest), use
60
+ [Tor Browser](https://www.torproject.org/download/) itself. torquests is built for
61
+ programmatic access to Tor and onion services from Python.