SReverseby Simpa Labs

Request signing

Reproducing an app's request signature in Python

A signature is a value the app computes from the request and sends as proof. Reproducing it in Python means finding the routine, recovering its inputs and matching its output for every request the server accepts.

What a request signature proves

The server recomputes the value from the request it received and compares the two. A match shows that whoever built the request knows the routine and the key. A captured signature is valid only for the request it was computed over, which is why pasting one into a script fails as soon as any covered field changes.

That property is also useful during analysis. If editing a field produces a rejection, the signature covers that field. If it does not, the field sits outside the signed material, and you can change it freely.

Find the routine

Signature code sits near the point where a request is finalised, because it needs the completed method, path, query and body. In an OkHttp app that place is an interceptor. In a Retrofit app it can be a converter or a call adapter. In an app that builds requests by hand, it is the last block before the socket write.

  • Search for digest and MAC names. The provider and algorithm strings are ordinary literals in most apps, and a search for them lands close to the routine.
  • Search for the header name the server expects. The same literal often appears once, at the point where the header is set.
  • Search for the key material. The key can be a literal in a constants class, a byte array in the dex, a value inside a native library, or an entry that only exists in the keystore.
  • Follow the arguments of the routine. The parameter list shows exactly which parts of the request are covered and in what order they are joined.

When the code is obfuscated, the strings usually survive even when the method names do not, so string searches remain useful. Android request signing covers the full recovery when the routine is hidden behind a protector.

Recover the exact input

Two implementations of the same algorithm still disagree when they feed it different bytes. The input is where most reproductions fail.

  • The join order changes the result. A signed string that concatenates the method, the path and the body produces a different digest if the order differs, so copy the order from the code rather than from intuition.
  • Empty values and missing values are not the same. A parameter present with an empty string usually hashes differently from a parameter that is absent, and the server checks one of those two forms.
  • Case and encoding change the bytes. Header names, percent encoding of query values and the character set used for the body all alter the input to the digest.
  • Query parameters need a fixed order. Servers that sign the query string expect the same ordering the client used, which is often a sorted order rather than the order the call site passed.
  • The key may be derived rather than stored. Some apps combine a stored secret with a device value or a session value, so the effective key changes between installs or between sessions.

Capture several requests that differ in one field each. Comparing them shows which parts of the request reach the signature and how sensitive the output is to each one.

Match the output before touching the rest of the request

Write one small Python function that takes the captured inputs and returns the captured signature. Run it against every capture you have, and treat a single mismatch as a real error rather than rounding noise. Only wire the function into a client once all captures match.

This order matters because it separates a signing bug from a transport or session bug. A client that signs incorrectly and sends correctly produces the same rejection as a client that signs correctly and sends badly, and debugging both at once wastes time.

Keep the routine maintainable

Store the signing logic in one module with the test vectors from your captures beside it. If the key rotates, the module is the only place that changes. If the server adds a signed field, the same test vectors show immediately which requests now fail.

Some apps change the signed material with a version value in the request or the response, which is why a reproduction that worked last month can stop working after an update. Signature and key rotation describes how to find that mechanism and reproduce it.

Reviewed 28 September 2026 · SReverse research desk

Start your full APK reconstruction

Send the full APK

Projects start at $120. Choose WhatsApp or email, then attach the APK in the app that opens. We reply within one hour with the next step and send the fixed quote after review.

Want us to contact you?