Secure Comparator

Secure Comparator #

Secure Comparator is an implementation of Zero-Knowledge Proof-based protocol, built around OTR SMP implementation, but ported to ECC domain and reinforced with additional checks and features.

Secure Comparator allows two parties to compare a shared secret without revealing it to potentially dishonest party (as well as to any listening-in third-party, of course).

If you want to study security and cryptography of Secure Comparator in depth, you might want to consult our whitepaper describing the development and cryptographic protocol. (Or there is a lighter “Explain me like I’m 5”-style article on zero-knowledge proofs in Cossack Labs blog.)

You may also want to read this comment on comparing the design goals and usage of Secure Session and Secure Comparator with SRP.

Secure Comparator use cases #

  • Login/password authentication: by sending login, client allows the server to locate the password (or its secure derivative) and start comparing it.
  • OTP reinforcement: authenticating actions within an already established communication/trust protocol.
  • Request authentication: authenticating a data request by proving the knowledge of some significant part of the data’s identification fields.
  • Repeated authentication: authenticating already established trust relationships using initial tokens and shared state data accumulated during the session.

Availability in Themis #

Being the most recent addition to the mainline Themis code to the date, Secure Comparator is yet to get all the shine and polish that our other features have. However, Secure Comparator is already available in multiple languages:

Protocol description #

Our SMP protocol is very similar to the SMP implementation in the Cypherpunk’s OTR, except for the fact that we use ECC for all computations.

Let’s suppose we have two parties with secrets x and y respectively, and they wish to know whether x = y. They use ed25519 curve with G as a base point. Alice starts the protocol.


  1. Picks two random numbers: a2 and a3.
  2. Computes G2a = a2 × G and G3a = a3 × G.
  3. Sends G2a and G3a to Bob.


  1. Picks two random numbers: b2 and b3.
  2. Computes G2b = b2 × G and G3b = b3 × G.
  3. Computes G2 = b2 × G2a and G3 = b3 × G3a.
  4. Picks a random number r.
  5. Computes Pb = r × G2 and Qb = r × G + y × G2.
  6. Sends G2b, G3b, Pb and Qb to Alice.


  1. Computes G2 = a2 × G2b and G3 = a3 × G3b.
  2. Picks a random number s.
  3. Computes Pa = s × G3 and Qa = s × G + x × G2.
  4. Computes Ra = a3 × (Qa − Qb).
  5. Sends Pa, Qa, Ra to Bob.


  1. Computes Rb = b3 × (Qa − Qb).
  2. Computes Rab = b3 × Ra.
  3. Checks whether Rab = Pa − Pb.
  4. Sends Rb to Alice.


  1. Computes Rab = a3 × Rb.
  2. Checks whether Rab = Pa − Pb.

If the Rab = Pa − Pb check is successful, each party is then convinced that x = y. Since Rab = (Pa − Pb) + (a3 × b3 × (x − y)) × G2, if x = y then Rab = (Pa − Pb) + 0 × G2 = Pa − Pb. If x ≠ y, then a3 × b3 × (x − y) × G2 is a random ECC point not known to any of the interacting parties, so no information is revealed.

Usage model #

Secure Comparator has two parties: initiator (client) and responder (server). They both initialise the Secure Comparator object, and, upon receiving anything from the communication channel, execute the next protocol step until the protocol is either successful or failed.

For example, you may look at the client and server in Python.

Implementation details #

Secure Comparator interface is described in src/themis/secure_comparator.h.

Secure Comparator does not implement the network layer, it is your responsibility to send and receive the messages from one side to another.

To create a Secure Comparator object, use the secure_comparator_create() function, then enter secret data you want to compare using secure_comparator_append_secret(). When the comparison is complete, destroy the Secure Comparator object with secure_comparator_destroy():

secure_comparator_t* secure_comparator_create(void);

themis_status_t secure_comparator_append_secret(
    secure_comparator_t* ctx,
    const void* secret_data,
    size_t      secret_data_length);

themis_status_t secure_comparator_destroy(secure_comparator_t* comp_ctx);

The side that initiates the comparison is called the client – you need to call secure_comparator_begin_compare() and send the resulting data to the other party.

themis_status_t secure_comparator_begin_compare(
    secure_comparator_t* ctx,
    void*   hello_data,
    size_t* hello_data_length);

Then the client and responding server proceed with the protocol, accepting messages with secure_comparator_proceed_compare() which returns replies that should be sent to the other party.

themis_status_t secure_comparator_proceed_compare(
    secure_comparator_t* ctx,
    const void* request_data,
    size_t      request_data_length,
    void*       response_data,
    size_t*     response_data_length);

When both reach THEMIS_SUCCESS status, the comparison is complete and the result can be checked with secure_comparator_get_result() which returns either THEMIS_SCOMPARE_MATCH or THEMIS_SCOMPARE_NO_MATCH.

themis_status_t secure_comparator_get_result(const secure_comparator_t *ctx);

Thread safety #

Secure Comparator requires additional synchronisation to be used concurrently from multiple threads. Read more about Themis thread safety guarantees.