Doridian / Doridian/OpenBambuAPI
Signing canonicalization corrections + live-verified project_file findings (LAN http url, S3 presigned rejection, clean_print_error, md5 semantics)
- Lingua principale
- Nessun dato sulla lingua
- Stelle
- 680
- Fork
- 96
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
# Corrections + new findings from live 2026-firmware P2S testing (signed commands, project_file)
Verified against a **Bambu Lab P2S on 2026 firmware, cloud mode** (X.509 app-cert route). Posting corrections to `cloud-x509-auth.md` plus several undocumented behaviors we confirmed live. Full write-up + tooling: https://github.com/Snail3D/bamboo-sense/blob/main/docs/CRACK.md
## 1. The signing canonicalization in cloud-x509-auth.md is wrong (sorted keys)
The doc's sorted-keys recipe does not verify. What actually works (confirmed by byte-level variant testing against the printer's error codes, and consistent with the decompiled signer in Randomblock1/bambu_connect_disasm):
- **Sign `JSON.stringify(envelope_without_header)` in original insertion order** — `"print"` (or `"security"`/`"system"`) object first, `"user_id"` **trailing, outside** the command object
- `sequence_id` must be a **number**, not a string (string sequence_ids change the error signature)
- `header` is then **spliced in before the final `}`** of the signed bytes: `signed_bytes[:-1] + ',"header":{...}' + '}'`
- `payload_len` = UTF-8 byte length of the signed string
- sig = base64(RSA-SHA256 PKCS1v15 over the signed bytes)
- cert_id = 32-hex-char leaf serial + issuer CN, e.g. `5A5A…CN=GLOF3813734089.bambulab.com` (issuer CN, not the leaf CN)
Useful error-code map (from the `security` result path):
| reason / shape | meaning |
|---|---|
| no `header` at all | rejected before parsing |
| `0x05024009`-family | malformed envelope |
| `0x0502400A`-family | header present, signature doesn't verify (wrong canonical form, wrong cert_id, or cert not installed) |
## 2. `print.project_file` — fully working recipe + the URL gotcha nobody documents
```json
{"print":{"sequence_id":,"command":"project_file","param":"Metadata/plate_1.gcode",
"url":"","md5":"","project_id":"0","profile_id":"0",
"task_id":"0","subtask_id":"0","use_ams":true,"ams_mapping":[],
"bed_leveling":true,"flow_cali":false,"vibration_cali":true,"layer_inspect":true,
"timelapse":false},"user_id":""}
```
- `md5` is the **md5 of the whole 3mf file**, NOT the `Metadata/plate_1.gcode.md5` stored inside it. Wrong md5 ⇒ task aborts in PREPARE with `print_error` 83902527 (0x0500403F), before any heating.
- `url` works as **plaintext**; `url_enc` (RSA to printer_cert) is accepted but not required on this firmware.
- `use_ams:false` makes the printer pull from the **external spool holder**; if that's empty it fails with HMS_0300-0200 (filament ran out). `ams_mapping` = tray index list, one entry per filament.
### The big one: `url` can be a plain LAN `http://` URL on a cloud-mode printer
We started a real print on a cloud-mode (not LAN-only) P2S by handing `project_file` a bare `http://192.168.x.x:8477/model.gcode.3mf` served by a laptop. Printer did HEAD + GET and pulled 18.7 MB over LAN. **Cloud-mode printer, zero Bambu cloud involvement, no SD card, no LAN-only mode.**
### The trap: presigned S3 URLs are rejected in PREPARE
Upload via `v1/iot-service/api/user/upload` (PUT 200) and hand the returned `https://s3.us-west-2.amazonaws.com/or-cloud-upload-prod/...?AWSAccessKeyId=...&Signature=...` URL to `project_file`: command is **ACKed SUCCESS**, printer shows PREPARE, then fails ~75 s later with `print_error` 83902527, no heating, HMS_0100-0100. Reproduced 3×. The firmware evidently only fetches from allow-listed hosts. If you see "ACK SUCCESS → PREPARE → FAILED 0x0500403F": it's the URL, not your signature/md5/AMS.
## 3. Undocumented `print.clean_print_error` command
`{"print":{"command":"clean_print_error","sequence_id":N}}` (signed normally) is accepted and **clears the HMS alarm list** (verified: HMS 0x10001 entry vanished). `gcode_state` remains `FAILED` as a sticky last-task-outcome field (same way FINISH persists). Notably, a LAN-url `project_file` still **starts while `gcode_state` reads FAILED** — the "ERROR STATE" refusals we saw were tied to the S3-url attempts, not to the latch. `system.restart`/`system.reboot` over MQTT are silently ignored.
## 4. State machine notes
- Signed `stop` during RUNNING aborts instantly (verified at 238 °C nozzle).
- `stop` from FINISH returns SUCCESS but is a no-op; `resume` from FAILED returns FAIL.
- New `project_file` while FAILED: depends on URL validity — LAN urls launched fine, S3 urls got `{"result":"FAIL","reason":"ERROR STATE"}`.
Happy to turn any of this into PRs against the relevant docs if you want — the full recipe, scripts and the dongle implementation (ESP32-S3 signing vault that installs its own cert via `app_cert_install` and signs commands on-chip) are MIT-licensed at Snail3D/bamboo-sense.
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Direzione di ricerca
Inizia con cloud-x509-auth.md e la documentazione sui live-testing in docs/CRACK.md. Confronta i risultati relativi a canonicalization, project_file, clean_print_error, URL, md5 e alla state machine con la documentazione esistente. Il lavoro è completato quando le correzioni e i comportamenti verificati sono documentati con le ricette e le avvertenze pertinenti.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- aws
- Ambito
- api, documentation, security
- Tipo di issue
- Documentazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Stato di attività
- Attiva
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 70/100