tlslp.client
Open a TLS client that responds to server messages.
A set of default valid messages and responses are included.
The client connects to a server, receives newline-delimited commands, and responds
one-by-one. The handshake consists of HELLO followed by a WORK challenge. The
WORK challenge must be resolved within 30 minutes with n_bits=36; it is solved by
invoking a compiled C++ helper (work_challenge).
- Main functions:
- prepare_client_socket:
Create a TLS-wrapped socket (secure or insecure).
- hasher:
Compute SHA256(token + payload) as a hex string.
- decipher_message:
Parse and validate a received command line.
- handle_work_cpp:
Run the WORK helper and parse its
RESULT:<suffix>output line.- define_response:
Create the protocol response for a single server command.
- main:
CLI entry point.
Functions
Convert parsed CLI args into a |
|
Build the argparse parser for the |
|
|
Connect to server and return True if connection was successful. |
|
Parse and validate a server message. |
|
Create a response for a single server command and enqueue it. |
|
Solve the WORK challenge using the external C++ helper. |
|
Hash a string using SHA256. |
|
Entry point for the CLI. |
|
Create a TLS-wrapped client socket. |
|
Run the WORK challenge C++ binary. |
Classes
|
Configuration for the TLS client CLI. |
- class tlslp.client.ClientConfig(server_host: str, ports: list[int], client_cert: str, private_key: str, ca_cert: str, work_binary: str, work_timeout: int, other_timeout: int, insecure: bool, log_level: str, tutorial: bool)
Bases:
objectConfiguration for the TLS client CLI.
This is built from CLI arguments and passed through to connection and message handling helpers.
- ca_cert: str
- client_cert: str
- insecure: bool
- log_level: str
- other_timeout: int
- ports: list[int]
- private_key: str
- server_host: str
- tutorial: bool
- work_binary: str
- work_timeout: int
- tlslp.client.args_to_client_config(ns: Namespace) ClientConfig
Convert parsed CLI args into a
ClientConfig.- Parameters:
ns (argparse.Namespace) – Parsed CLI args.
- Returns:
Normalized configuration.
- Return type:
- tlslp.client.build_client_parser() ArgumentParser
Build the argparse parser for the
tlslp-clientCLI.- Returns:
Configured parser.
- Return type:
argparse.ArgumentParser
- tlslp.client.connect_to_server(sock: socket, server_host: str, port: int) bool
Connect to server and return True if connection was successful.
- Parameters:
sock (socket.socket) – The socket to connect to.
server_host (str) – The server_host to connect to.
port (int) – The port to connect to.
- Returns:
True if connection was successful, False otherwise.
- Return type:
bool
- tlslp.client.decipher_message(message: str, valid_messages: set[str]) list[str]
Parse and validate a server message.
Splits the message into whitespace-delimited tokens and validates that the first token is a known command. If the server sends only a command (no argument), an empty second token is appended so callers can uniformly access
args[1].- Parameters:
message (str) – The received message line (with or without trailing newline).
valid_messages (set[str]) – Allowed command names.
- Returns:
Parsed tokens, with at least two elements.
- Return type:
list[str]
- Raises:
ValueError – If the message is empty or the command is not in
valid_messages.
Examples
>>> from tlslp.client import decipher_message >>> vm = {"EMAIL1", "HELLO", "WORK", "DONE", "FAIL"} >>> decipher_message("EMAIL1 LGTk\n", vm) ['EMAIL1', 'LGTk']
- tlslp.client.define_response(args: list[str], token: str, valid_messages: set[str], queue: Queue, responses: dict[str, str] = {'ADDR_LINE1': '234 Evergreen Terrace', 'ADDR_LINE2': 'Springfield', 'BIRTHDATE': '99.99.1982', 'COUNTRY': 'USA', 'EMAIL1': 'elliottbache@gmail.com', 'EMAIL2': 'elliottbache2@gmail.com', 'FULL_NAME': 'Elliott Bache', 'SOCIAL': 'elliottbache@hotmail.com'}, bin_path: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/tls-line-protocol/checkouts/latest/src/tlslp/_bin/work_challenge')) None
Create a response for a single server command and enqueue it.
This computes the appropriate response for a parsed server message and places a tuple
(is_err, result)intoqueue.- Parameters:
args (list[str]) – Parsed server tokens (command is
args[0]).token (str) – Current authentication data (set after receiving
WORK).valid_messages (set[str]) – Allowed command names.
queue (multiprocessing.Queue) – Queue-like object that supports
put(...).responses (dict[str, str], optional) – Static responses for body commands.
bin_path (Path, optional) – Path to the WORK solver binary.
- Returns:
None
Examples
>>> import tlslp.client as c >>> class Q: ... def __init__(self): self.items = [] ... def put(self, x): self.items.append(x) >>> q = Q() >>> c.define_response(["HELLO"], token="", valid_messages={"HELLO"}, queue=q, responses={}) >>> q.items [(False, 'HELLOBACK\n')]
- tlslp.client.handle_work_cpp(token: str, n_bits: str, bin_path: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/tls-line-protocol/checkouts/latest/src/tlslp/_bin/work_challenge'), timeout: int = 1800) str
Solve the WORK challenge using the external C++ helper.
Runs the WORK binary and parses the first stdout line starting with
RESULT:. The returned suffix includes a trailing newline to match the wire protocol.- Parameters:
token (str) – Authentication data from the server.
n_bits (str) – Required number of trailing zero bits
bin_path (Path, optional) – Path to the WORK solver binary.
timeout (int, optional) – Subprocess timeout in seconds.
- Returns:
The suffix followed by
"\n".- Return type:
str
- Raises:
ValueError – If no
RESULT:line is found or the suffix is empty.subprocess.CalledProcessError – If the solver exits non-zero.
Examples
>>> from pathlib import Path >>> import tlslp.client as c >>> class R: # fake CompletedProcess ... stdout = "RESULT:abcd\n" >>> c.run_work_binary = lambda *a, **k: R() >>> c.handle_work_cpp("AUTH", "4", bin_path=Path("work_challenge")) 'abcd\n'
- tlslp.client.hasher(token: str, input_string: str) str
Hash a string using SHA256.
Concatenates
tokenandinput_stringand returns the SHA256 digest in lowercase hex.- Parameters:
token (str) – Authentication data provided by the server.
input_string (str) – ASCII payload provided by the server.
- Returns:
SHA256(token + input_string) as a hex string.
- Return type:
str
Examples
>>> from tlslp.client import hasher >>> token = "AUTH" >>> hasher(auth, "LGTk") '189af41571a36ba3655451530a84e33f018bdca2'
- tlslp.client.main(argv: Sequence[str] | None = None) int
Entry point for the CLI.
- Parameters:
argv – sys.argv[1:] is used.
- Returns:
0 on success; nonzero on error.
- Return type:
Process exit code
- Side effects:
Opens network connections, prints to stdout/stderr.
- tlslp.client.prepare_client_socket(ca_cert_path: str, client_cert_path: str, private_key_path: str, server_host: str, is_secure: bool = False) socket
Create a TLS-wrapped client socket.
In secure mode (
is_secure=True), the client verifies the server certificate againstca_cert_pathand enables hostname verification.In insecure mode (
is_secure=False), certificate verification is disabled and hostname checks are disabled; to avoid accidental misuse, insecure mode is only allowed forlocalhost.The returned socket has a default timeout of
min(DEFAULT_OTHER_TIMEOUT, DEFAULT_WORK_TIMEOUT); callers may override this viasettimeout(...).- Parameters:
ca_cert_path (str) – Path to CA certificate (PEM).
client_cert_path (str) – Path to client certificate (PEM).
private_key_path (str) – Path to client private key (PEM).
server_host (str) – Server hostname.
is_secure (bool, optional) – If True, verify the server certificate and hostname.
- Returns:
A TLS-wrapped socket ready to
connect(...).- Return type:
socket.socket
- Raises:
ValueError – If insecure mode is requested for a non-local host.
- tlslp.client.run_work_binary(bin_path: Path, token: str, n_bits: str, timeout: int = 1800) CompletedProcess
Run the WORK challenge C++ binary.
- Parameters:
bin_path (Path) – The path of the C++ binary.
token (str) – The authentication data to use.
n_bits (str) – The n_bits to use.
timeout (int, optional) – The timeout to use.
- Returns:
The completed process.
- Return type:
subprocess.CompletedProcess
Notes
- In subprocess.run,
the environment variables are scrubbed, leaving only the simplest (env={“LC_ALL”: “C”})
the stdout and stderr are returned as text and not bytes (text=True, capture_output=True)
the exit status is returned and a CalledProcessError exception is raised if non-zero (check=True)
the timeout is set at 30 minutes (timeout=timeout)
the current working directory is set as the binary’s directory to avoid flakiness in tests (cwd=str(cpp_binary_path.parent))