Sunday 13 September 2015

Diffie-Hellman key exchange

Let's say you're in the middle of your classroom and you want to send a message to your friend located at the back (by shouting it out). However you don't want your other classmates to understand the message.

Well you've learned in your computer security class that if you and your friend both have a shared key, you can encrypt the message using the key, send it to him, and then he can then decrypt the message it using the same key.

However in this case both of you don't have any shared key.
What can you do?

In fact this seems to be impossible, but it isn't. You can use the Diffie-Hellman key exchange method.

This is explained beautifully in this image taken from Wikipedia:

You are Alice and your friend is Bob.
The dark orange and dark blue paint are some random secrets decided by each of you.

Everyone in your classroom knows the yellow paint. They also know the "light orange" paint and the "light blue" paint (since this is exchanged publicly by Alice and Bob)

After applying the above method, both Alice and Bob will end up with a common secret: the dark brown paint which they can subsequently use as a shared key to exchange secret messages.

Let's see where the difficulty arises for your classmates to obtain the dark brown paint (the shared key)

They know the yellow, light orange and light blue paints.
But from the yellow and light orange paint, they cannot recover the dark orange paint.
And from the yellow and light blue paint, they cannot recover the dark blue paint.
Thus they cannot obtain the dark brown paint.

In fact, the above paint operations can be defined by some mathematical functions which are easy to compute (mixing paints) but computationally difficult to reverse (unmixing paints) where it would take millions or billions of years for even the fastest supercomputers to find out the answer.

The original implementation of the protocol uses the function gA mod p (known as Modular Exponentiation function)
Someone knowing g & p (the yellow paint) and gA mod p (the light orange or light blue paint) cannot find the value of A (the dark orange or dark blue paint) in a feasible amount of time for large values (known as Discrete Logarithm function).

You can use this method to avoid man-in-the-middle (MITM) attacks, even if someone is listening to your communications from the beginning before you've agreed on a common secret key.


10 comments:

  1. On the implementation side, you can have heartbleed-like attacks, where p,q and other intermediate values may be free'ed (and floating around in the virtual memory), but not actually cleared, by writing 0000000 in those locations :)

    ReplyDelete
  2. Nice observation :)
    Is there anyway you can secure your stack/heap? (e.g. if you need to reuse the same variables)
    For example, a separate process could be used to compute sensitive things and then they communicate via messaging (but that would be overkill I guess)

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. Or enforce an upper layer on any low level functions, to add a pointer that will give you context,

      e.g

      void *memcpy(void *str1, const void *str2, size_t n)
      void *memscpy(void *str1, const void *str2, size_t n, void *marker)

      Marker being defined as
      marker[0]->start
      marker[1]->end

      each client that you are instantiating, you create a marker start/end in memory.
      So each time you are doing an actual memscpy, underneath, you can do bound checks. Same goes for increasing size allocated, which you can do any check with if your start/end to see if they cross against an index of addresses.


      e.g your application can't go out of bounds if your memscpy it doing proper bounds check before actually sending anything to memcpy, having a context, is better, e.g:


      -------------------------------------
      -----[jon's marker start]-----
      -----[jon's data ]---------------
      -----[jon's marker end]------
      -----[sarah's marker start]-
      -----[sarah's data]-------------
      -----[sarah's data]-------------
      -----[sarah's data]-------------
      -----[sarah's marker end]-
      :
      :


      but that'll require another layer of memory management over an already existing one, and is way too costly cpu wise.

      Though that's just an over the head thought

      Delete
    3. s/which you can do any check with /which you can do any check with ,/

      s/if your memscpy it doing/if your memscpy is doing/

      Delete
    4. Thanks Selven, that's an interesting and easy way of protecting yourself. :) you may even keep the marker pointer inside the object itself.

      Delete
  3. A simple solution consists of writing 0x000 or or any dummy values right before you free the sensitive variable :)

    e.g:
    https://git.openssl.org/?p=openssl.git;a=commitdiff;h=9f040d6decca7930e978784c917f731e5c45e8f0

    ReplyDelete
  4. Nicely explained in a simple way.

    ReplyDelete