CRY-PTO
Challenge
The service leaks the "signature" of a fixed user string, then lets you request the signature of any query bytes you send, and finally accepts a signature you hand back — if it verifies as the signature for root, you get root's response. The signing function is linear over XOR: it doesn't bind the message strongly enough to stop you from combining two known signatures to derive a third.
Solution
Query user XOR root. XOR-ing the returned signature for that query with the already-leaked signature for user cancels out the shared part of the keystream/state and produces exactly the signature root would have gotten — without ever knowing root's actual signing secret.
user = b"babyuser" root = b"chadr00t" query = xor_bytes(user, root) … send query, receive query_sig … root_sig = xor_bytes(user_sig, query_sig) … send root_sig back to the service …
Handing back root_sig passes verification as root's signature and the service returns the flag.