Authentication (Firmware 7.18+)

Starting with firmware version 7.18, ZWO added a mandatory challenge-response handshake to the Seestar’s JSON-RPC interface (port 4700). Third-party software must complete this handshake before the telescope will accept any commands.

seestarpy handles this transparently via the auth module — once you place the key file in the right location, every connection authenticates automatically.

How the handshake works

The authentication is a 3-step RSA challenge-response exchange that happens immediately after a TCP connection is established:

  1. Challenge request — seestarpy sends get_verify_str to the telescope. The telescope replies with a random string (the “challenge”).

  2. Signature — seestarpy signs the challenge with an RSA private key using SHA-1 (PKCS#1 v1.5), base64-encodes the result, and sends it back via verify_client. This proves possession of the correct key without transmitting it.

  3. Confirmation — seestarpy sends pi_is_verified as a final acknowledgement. The telescope responds, and authentication is complete.

All three steps happen behind the scenes. Your code simply calls raw.test_connection() (or any other command) and it works.

Note

On older firmware (< 7.18), the telescope does not recognise the get_verify_str method and returns error code 103. seestarpy detects this and skips authentication, so the same code works on both old and new firmware.

Setup

All you need is the RSA private key in PEM format. seestarpy ships with a built-in extractor that pulls the key out of a Seestar APK you have obtained, and the cryptography signing library is now a standard dependency installed alongside seestarpy.

Note

If cryptography somehow fails to import, seestarpy falls back to shelling out to the openssl command-line tool, so signing still works on systems where that tool is on PATH.

Extracting the key from an APK

Obtain the official ZWO Seestar Android APK yourself (for example from an APK mirror site such as APKPure), then run:

python -m seestarpy.extract_pem /path/to/Seestar_v3.1.2.apk

On success the key is written to ~/.seestarpy/seestar.pem, which is one of the locations seestarpy auto-discovers on every connection.

Useful flags:

  • -o PATH — write to a custom location.

  • --stdout — print the key(s) to stdout instead of writing a file. Handy if the APK contains multiple keys.

  • -q — suppress progress messages.

The extractor is a generic utility: it opens the APK as a ZIP, reads the native library lib/arm64-v8a/libopenssllib.so (or the armeabi-v7a variant), runs a strings(1)-style scan, and matches any -----BEGIN PRIVATE KEY----- block it finds. It has no ZWO-specific logic and ships no key of its own.

Key auto-discovery

seestarpy searches for the key in this order:

  1. The SEESTAR_KEY_PATH environment variable (if set and the file exists).

  2. seestar.pem in the current working directory.

  3. ~/.seestarpy/seestar.pem (i.e. a .seestarpy folder in your home directory) — this is where the extractor writes by default.

On Windows, ~/.seestarpy/ resolves to C:\Users\<you>\.seestarpy\.

You can also set the path at runtime:

from seestarpy import auth
auth.set_key_path("/path/to/seestar.pem")

Verifying it works

from seestarpy import auth, raw

# Confirm the key was found
print(auth.KEY_PATH)       # Should print a path, not None

# Test the connection (auth happens automatically)
result = raw.test_connection()
print(result["code"])      # 0 = success

If auth.KEY_PATH is None, the key was not found in any of the three auto-discovery locations.

About the RSA key

The key is not unique per device or per user. Every copy of the app contains the same key, and it has remained identical across APK versions (verified with v3.0.2 and v3.1.2).

The telescope’s firmware holds the corresponding public key and uses it to verify signatures during the handshake. Because the private key is a single global key, the handshake only proves that the connecting software has access to the same key as the official app — it does not identify individual users or devices.