Skip to content

Commit 9430a25

Browse files
committed
enhance section on signature
1 parent e3c655d commit 9430a25

2 files changed

Lines changed: 14 additions & 6 deletions

File tree

docs/technical_writeup.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ We need either the public key (stored on Roborock's servers) or the private key
9090

9191
Remember step 4 of the onboarding flow - the vacuum hits the `/region` endpoint and passes a `signature` parameter. That signature is an RSA PKCS1v1.5 SHA-256 signature over the query string, signed with the vacuum's private key. We can't access the private key, but we don't need to. We just need the public key. With enough signature samples, we can actually determine the public key.
9292

93-
Here's the math. An RSA signature is `sig = msg^d mod n`, and verification is `sig^e mod n == msg`. We know `e` (65537 is the standard RSA public exponent used by virtually every implementation - including here), we know the message (it's the query string), and we know the signature (it's right there in the request). What we don't know is `n` — the RSA modulus, which is the public key.
93+
Here's the math. RSA PKCS#1 v1.5 signing computes `sig = pad(SHA256(msg))^d mod n`, where `pad()` is the deterministic EMSA-PKCS1-v1.5 encoding (a fixed ASN.1 prefix + the hash, right-padded into a full block). Verification checks `sig^e mod n == pad(SHA256(msg))`. We know `e` (65537 is the standard RSA public exponent used by most implmenetations), we can compute `pad(SHA256(msg))` ourselves (it's deterministic given the query string), and we know the signature as it is included in the REST request. What we don't know is `n` — the RSA modulus, which is the public key.
9494

95-
If we rearrange the verification equation: `sig^e - msg = k * n` for some integer `k`. That means `sig^e - msg` is a multiple of `n`. If we collect two different signed requests from the vacuum (different query strings, different signatures), we get two different multiples of `n`. The GCD of those two values gives us `n` or `n` times some small cofactor that we can divide out.
95+
If we rearrange the verification equation: `sig^e - pad(SHA256(msg)) = k * n` for some integer `k`. That means the difference is a multiple of `n`. If we collect two different signed requests from the vacuum (different query strings, different signatures), we get two different multiples of `n`. The GCD of those two values gives us `n` - or `n` times some small cofactor that we can divide out. The padding being deterministic is what makes this work — if it included any randomness, we couldn't compute the padded value and the recovery would be impossible.
9696

9797
So the approach is:
9898
1) During onboarding, we inject our server URL so the vacuum connects to us.

mkdocs.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,33 @@ theme:
55
palette:
66
- media: "(prefers-color-scheme: light)"
77
scheme: default
8-
primary: teal
9-
accent: teal
8+
primary: deep purple
9+
accent: amber
1010
toggle:
1111
icon: material/brightness-7
1212
name: Switch to dark mode
1313
- media: "(prefers-color-scheme: dark)"
1414
scheme: slate
15-
primary: teal
16-
accent: teal
15+
primary: deep purple
16+
accent: amber
1717
toggle:
1818
icon: material/brightness-4
1919
name: Switch to light mode
20+
font:
21+
text: Inter
22+
code: Roboto Mono
23+
icon:
24+
repo: fontawesome/brands/github
2025
features:
2126
- navigation.instant
2227
- navigation.tracking
2328
- navigation.sections
29+
- navigation.expand
2430
- navigation.top
2531
- content.code.copy
2632
- toc.follow
33+
- search.suggest
34+
- search.highlight
2735

2836
markdown_extensions:
2937
- admonition

0 commit comments

Comments
 (0)