< Return to Video

Key Derivation (14 min)

  • 0:00 - 0:04
    Well, we're almost done with our
    discussion of symmetric encryption. There
  • 0:04 - 0:06
    are just a couple of odds and ends that
    I'd like to discuss before we move on to
  • 0:06 - 0:10
    the next topic. So the first thing I'd
    like to mention is how we derive many keys
  • 0:10 - 0:14
    from one key. And it, actually, this comes
    up all the time in practice, so I'd like
  • 0:14 - 0:18
    to make sure you know how to do this
    correctly. So what's the setting that
  • 0:18 - 0:23
    we're looking at? Well, imagine we have a
    certain source key that's generated by one
  • 0:23 - 0:26
    of, a number of methods. Imagine the
    source key is generated by a hardware
  • 0:26 - 0:30
    random number generator or perhaps is
    generated by a key exchange protocol
  • 0:30 - 0:34
    which we're going to discuss later. But
    anyhow, there are a number of ways in
  • 0:34 - 0:38
    which a source key might be generated
    between Alice and Bob, such that the
  • 0:38 - 0:43
    attacker doesn't know what the source key
    is. But now, as we said, in many cases, we
  • 0:43 - 0:47
    actually need many keys to secure a
    session, not just one single source key.
  • 0:47 - 0:51
    For example, if you remember, in TLS there
    were unidirectional keys and we
  • 0:51 - 0:55
    needed keys in each direction. And in
    fact, in each direction, we needed
  • 0:55 - 0:59
    multiple keys. We needed a MAC key, we
    needed an encryption key. We need an IV,
  • 0:59 - 1:03
    and so on. Similarly nonce based
    encryption, you remember, there were
  • 1:03 - 1:08
    multiple keys that were being used, and so
    on. And so, the question is, how do we use
  • 1:08 - 1:12
    the one source key that we just derived,
    either from a hardware process or
  • 1:12 - 1:16
    by key exchange, and generate a bunch of
    keys from it that we could then use to
  • 1:16 - 1:21
    secure our session. The way that's done,
    is using a mechanism called a key
  • 1:21 - 1:25
    derivation function, KDF. And I want to
    talk a little bit about how KDF's are
  • 1:25 - 1:30
    constructed. So first of all, suppose we
    have a secure PRF, that happens to have
  • 1:30 - 1:35
    key space K. And now, suppose that it so
    happens that our source key SK is uniform
  • 1:35 - 1:41
    in the key K. In this case, the source key
    is, in fact, a uniform random key for the
  • 1:41 - 1:46
    secure PRF F. And we can use it directly to
    generate keys, all the keys that we need
  • 1:46 - 1:50
    to secure the session. So in this case,
    the KDF is really simple. The key
  • 1:50 - 1:54
    derivation function would just work as
    follows. It would take as input the
  • 1:54 - 1:58
    source key. It would take an input, a
    parameter context, which I'm gonna
  • 1:58 - 2:03
    describe in just a minute. And then it's
    gonna take a length input as input as
  • 2:03 - 2:08
    well. And then what it will do is it will
    basically evaluate the PRF on zero. Then
  • 2:08 - 2:12
    it will evaluate the PRF on one. Then it
    will evaluate the PRF on two, up until L.
  • 2:12 - 2:16
    And I will talk about what this context is
    in just a second. And then, basically, you
  • 2:16 - 2:20
    would use as many bits of the output as
    you would need to generate all the keys
  • 2:20 - 2:24
    for the session. So, if you need unidirectional keys you would generate, you
  • 2:24 - 2:28
    know, one key in each direction where each key
    might include an encryption key and a MAC
  • 2:28 - 2:32
    key. And so, you would basically generate
    as many bits as you need and then finally
  • 2:32 - 2:36
    cut off the output at the time when you've
    generated enough keys to secure your
  • 2:36 - 2:41
    session. Okay so this is a fairly straight
    forward mechanism it's basically using the
  • 2:41 - 2:46
    secure PRF as a pseudo random generator.
    And the only question is what is its
  • 2:46 - 2:49
    context string. Well, I'll tell you that
    the context string is basically a unique
  • 2:49 - 2:54
    string that identifies the application. So
    in fact you might have multiple
  • 2:54 - 2:58
    applications on the same system that's
    trying to establish multiple secure keys.
  • 2:58 - 3:03
    Maybe you have SSH running as one process,
    you have a web server running as another process,
  • 3:03 - 3:09
    IPsec as a third process and all three need
    to have secret keys generated. And this
  • 3:09 - 3:14
    context variable basically tries to separate
    the three of them. So, let me ask you,
  • 3:14 - 3:17
    more precisely, what do you think
    the purpose of this context variable is?
  • 3:19 - 3:22
    So I guess I've given
    it away and this context variable is
  • 3:22 - 3:26
    supposed to basically separate
    applications, so that even if, for
  • 3:26 - 3:31
    example, the three services that we just
    talked about, SSH, web server, and IPsec,
  • 3:31 - 3:36
    if they all happen to obtain the same
    source key from the hardware random number
  • 3:36 - 3:40
    generator then the context since it's
    different for the three apps will make
  • 3:40 - 3:46
    sure that they still get three independent
    strings that they can then use to secure
  • 3:46 - 3:50
    the sessions. I just want you to remember
    that, even though this is actually fairly
  • 3:50 - 3:54
    straightforward, and we discussed this
    before, the context string is actually
  • 3:54 - 3:57
    important, and it does need to be specific
    to the application, so that each
  • 3:57 - 4:01
    application gets its own session keys,
    even if multiple applications happen to
  • 4:01 - 4:05
    sample the same SK. The next
    question is, what do we do if the source
  • 4:05 - 4:10
    key actually isn't uniform? Well, now we
    got a problem. If the source key is not a
  • 4:10 - 4:14
    uniform key for the pseudo random function
    then we can no longer assume that the
  • 4:14 - 4:19
    output of the pseudo random function is
    indistinguishable from random. In fact, if
  • 4:19 - 4:24
    we just use the KDF that we just described
    then the output might not look random to
  • 4:24 - 4:27
    the adversary and then he might be able to
    anticipate some of the session keys that
  • 4:27 - 4:32
    we'll be using and thereby break the
    session. So then we have a problem. Now
  • 4:32 - 4:36
    why would this source key not be uniform?
    Well there are many reasons why this
  • 4:36 - 4:40
    happened. For example if you use a key
    exchange protocol, it so happens typically
  • 4:40 - 4:43
    that key exchange protocols will generate a
    high entropy key. But the
  • 4:43 - 4:47
    high entropy key is gonna be
    distributed in some subspace of the key
  • 4:47 - 4:51
    space. So it's not going to be a uniform
    string. It will be uniform in some
  • 4:51 - 4:56
    subset of a larger set, And we'll see
    examples of that as soon as we talk about
  • 4:56 - 5:00
    key exchange protocols. And so KDFs have
    to kind of accommodate for the fact that
  • 5:00 - 5:04
    key exchange protocols actually don't
    generate uniform bit strings. The other
  • 5:04 - 5:09
    problem is, that, in fact, the hardware
    random number generator you're using might
  • 5:09 - 5:13
    actually produce biased outputs. We don't
    wanna rely on the non bias of the hardware
  • 5:13 - 5:17
    random number generator. And so all we
    want to assume is that it generates a high
  • 5:17 - 5:22
    entropy string, but one that might be
    biased. In which case, we have to somehow
  • 5:22 - 5:27
    clean this bias. And so this introduces
    this, this paradigm for building KDFs.
  • 5:27 - 5:32
    This is called the extract-then-expand
    paradigm, where the first step
  • 5:32 - 5:37
    of the KDF is to extract a pseudo random
    key from the actual source key. So in a
  • 5:37 - 5:41
    picture you can think about it like this.
    In some sense these are the different
  • 5:41 - 5:45
    possible values of the source key. This is
    the horizontal line and the vertical axis
  • 5:45 - 5:50
    is basically the probability of each one
    of these values, and you can see that this
  • 5:50 - 5:53
    is a kind of a bumpy function which would
    say that the source key is not uniformly
  • 5:53 - 5:59
    distributed in the key space. What we do
    in this case is we use what's called an
  • 5:59 - 6:03
    extractor. So an extractor is something
    that takes a bumpy distribution and makes
  • 6:03 - 6:07
    it into a uniform distribution over the
    key space. In our case we're actually just
  • 6:07 - 6:10
    gonna be using what are called
    computational extractors, namely
  • 6:10 - 6:15
    extractors that don't necessarily produce
    uniform distribution at the end but
  • 6:15 - 6:20
    they generated distribution that's
    indistinguishable from uniform.
  • 6:23 - 6:27
    Now extractors typically take as input
    something called a salt, and a salt just
  • 6:27 - 6:31
    like in a salad, it kind of adds flavor to
    things, what it does is basically kind of
  • 6:31 - 6:36
    jumbles things around, so that no matter
    what the input distribution is, the output
  • 6:36 - 6:40
    distribution is still going to be
    indistinguishable from random. So a salt
  • 6:40 - 6:44
    basically, what is it? It's a non-secret
    string, so it's publicly known. It doesn't
  • 6:44 - 6:49
    matter if the adversary knows what the
    salt is, and it's fixed forever. The only
  • 6:49 - 6:53
    point is that when you chose it, you chose
    one at random. And then the hope is that
  • 6:53 - 6:57
    the funny distribution that you're trying
    to extract from kinda doesn't inherently
  • 6:57 - 7:00
    depends on the salt that you chose and
    hence as a result using your salt, you
  • 7:00 - 7:04
    will actually get a distribution that
    looks indistinguishable from random. So
  • 7:04 - 7:07
    essentially the salt, you know, you can
    just bang it the keyboard a couple of
  • 7:07 - 7:10
    times when you generate it but it just
    needs to be something that's random
  • 7:10 - 7:14
    initially but then it's fixed forever, and
    it's fine if the adversary knows what
  • 7:14 - 7:20
    it is and nevertheless the extractor is
    able to extract the entropy and output a
  • 7:20 - 7:25
    uniformly random string K. In some sense the
    salt is only there to defend against
  • 7:25 - 7:30
    adversarially bad distributions that might
    mess up our extractor. Okay, so now that
  • 7:30 - 7:35
    we have extracted a pseudo random key.
    Now, we might as well just use it in a KDF
  • 7:35 - 7:39
    that we just saw using a secure
    pseudo random function to expand the key
  • 7:39 - 7:43
    into as many bits as we need to actually
    secure the session. Okay, so there are
  • 7:43 - 7:47
    these two steps. The first one is we
    extract a pseudo-random key, and then once
  • 7:47 - 7:52
    we have a pseudo-random key we already
    know how to extend it into as many keys as
  • 7:52 - 7:56
    we need using a pseudo-random function. So
    the standardized way of doing this is
  • 7:56 - 8:01
    called HKDF. This is a KDF, a key derivation function that's built from HMAC.
  • 8:01 - 8:07
    And here HMAC is used both as the PRF for
    expanding and an extractor for extracting
  • 8:07 - 8:12
    the initial pseudo-random key. So let me
    explain how this works. So in the extract
  • 8:12 - 8:17
    step, we're gonna use our salt which you
    remember is a public value just happened to
  • 8:17 - 8:21
    be generated at random at the beginning of
    time. And we use this salt as the HMAC
  • 8:21 - 8:28
    key. And then the source key we're gonna
    use as the HMAC data. So we're kind of
  • 8:28 - 8:32
    using a public value as a key. And
    nevertheless, one can argue that HMAC has
  • 8:32 - 8:38
    extraction properties, such that, when we
    apply HMAC, the resulting key is going to
  • 8:38 - 8:42
    look indistinguishable from random,
    assuming that the source key actually has
  • 8:42 - 8:47
    enough entropy to it. And now that we have
    the pseudo random key we're simply going
  • 8:47 - 8:52
    to use HMAC as a PRF to generate a
    session key of you know as many bits as we
  • 8:52 - 8:56
    need for the session keys. Okay. So that
    basically concludes our discussion of
  • 8:56 - 9:01
    HKDF. And I just want you to remember
    that, once you obtain a source key, either
  • 9:01 - 9:05
    from hardware or from a key exchange
    protocol, the way you convert it into
  • 9:05 - 9:10
    session keys is not by using that sample
    directly. You would never use a source key
  • 9:10 - 9:14
    directly as a session key in a protocol.
    What you would do is you will run the
  • 9:14 - 9:18
    source key through a KDF. And the KDF
    would give you all the keys and output
  • 9:18 - 9:23
    that you need, for, the randomness, for
    the random keys to be used in your
  • 9:23 - 9:27
    protocol. And a typical KDF to use is
    HKDF, which is actually getting quite a
  • 9:27 - 9:32
    bit of traction out there. Okay. The last
    topic I wanna talk about in this segment
  • 9:32 - 9:36
    is, how do you extract keys from
    passwords. These are called password based
  • 9:36 - 9:42
    KDFs or PBKDFs. The problem here is
    that passwords have relatively low
  • 9:42 - 9:46
    entropy. In fact, we're gonna talk about
    passwords later on in the course when we
  • 9:46 - 9:50
    talk about user authentication. And so,
    I'm not gonna say too much here. I'll just
  • 9:50 - 9:54
    say passwords generally have very little
    entropy estimated on the order of twenty
  • 9:54 - 9:59
    bits of entropy, say. And as a result,
    there is simply not enough entropy to
  • 9:59 - 10:03
    generate session keys out of a password.
    And yet we still need to do it very
  • 10:03 - 10:07
    frequently. We still need to derive
    encryption keys and MACs and so on out of
  • 10:07 - 10:11
    passwords, so the question is how to do
    it. The first thing is, you know, for this
  • 10:11 - 10:15
    kind of purpose, don't use HKDF. That's
    not what it's designed for. What will
  • 10:15 - 10:19
    happen is that the derived keys will
    actually be vulnerable to something called
  • 10:19 - 10:22
    a dictionary attack, which we're gonna
    talk about much later in the course when
  • 10:22 - 10:28
    we talk about user authentication. So, the
    way PBKDFs defend against this low entropy
  • 10:28 - 10:33
    problem that results in a dictionary
    attack is by two means. First of all, as
  • 10:33 - 10:39
    before they use a salt, a public,
    random value that's fixed forever. But in
  • 10:39 - 10:43
    addition, they also use what's called a
    slow hash function. And let me describe
  • 10:43 - 10:49
    kind of the standard approach to deriving
    keys from passwords. This is called PKCS#5,
  • 10:49 - 10:54
    and in particular, the version I'll describe
    is what's called PBKDF1. And I
  • 10:54 - 10:57
    should say that this mechanism is
    implemented in most crypto libraries so
  • 10:57 - 11:01
    you shouldn't have to implement this
    yourself. All you would do, you know, you
  • 11:01 - 11:04
    would call a function, you know, derived
    key from password. You would give the
  • 11:04 - 11:08
    password in as input, and you would get a
    key as output. But you should be aware of
  • 11:08 - 11:12
    course that this key is not going to have
    high entropy so in fact it will be
  • 11:12 - 11:17
    guessable. What these PBKDFs try to do is
    make the guessing problem as hard as
  • 11:17 - 11:21
    possible. Okay. So the way they work,
    first of all, is, as we said, they
  • 11:21 - 11:26
    basically hash, the concatenation of the
    password and the salt. And then the hash
  • 11:26 - 11:29
    itself is designed to be a very slow hash
    function. And the way we build a slow hash
  • 11:29 - 11:34
    function is by taking one particular hash
    function, say, SHA-256, and we
  • 11:34 - 11:39
    iterate it many, many times, C times. So
    you can imagine 1000 times, perhaps even a
  • 11:39 - 11:43
    million times. And what do I mean by
    iterating it? So, well, we take the
  • 11:43 - 11:48
    password and the salt. And we put them
    inside of one input to the hash function.
  • 11:48 - 11:54
    And then we apply the hash function, oops,
    let me write it like this. And then we
  • 11:54 - 11:58
    apply the hash function and we get an
    output, and then we apply the hash
  • 11:58 - 12:01
    function again and we get another output.
    And we do this again and again and again
  • 12:01 - 12:06
    maybe a thousand times or a million times
    depending on how fast your processors are
  • 12:06 - 12:11
    and then finally we get the final output
    that we actually output as, as the key
  • 12:11 - 12:15
    output of this key derivation function.
    Now what is the point here? Iterating a
  • 12:15 - 12:19
    function 10,000 times or even a million
    times is going to take very little time on
  • 12:19 - 12:23
    a modern CPU, and as a result, it doesn't
    really affect the user's experience. The
  • 12:23 - 12:28
    user types in his password, it gets hashed
    a million times and then it gets output.
  • 12:28 - 12:32
    And maybe that could even take, you know a
    tenth of a second and the user wouldn't
  • 12:32 - 12:35
    even notice it. However the attacker, all
    he can do is he can try all the passwords
  • 12:35 - 12:40
    in the dictionary, because we know people
    tend to pick passwords in dictionaries,
  • 12:40 - 12:44
    and so he could just try them one by one,
    remember the SALT is public, so he knows
  • 12:44 - 12:49
    what the SALT is. And so he can just try this
    hash one by one. However because the hash
  • 12:49 - 12:54
    function is slow, each attempt is gonna
    take him a tenth of second. So if he needs
  • 12:54 - 12:58
    to run through a dictionary, you know, with,
    with a 200 billion passwords in it,
  • 12:58 - 13:02
    because the hash function is slow, this is
    gonna take quite awhile. And by doing
  • 13:02 - 13:07
    that, we slow down the dictionary attack,
    and we make it harder for the attacker to
  • 13:07 - 13:12
    get our session keys. Not impossible, just
    harder. That's all this is trying to do.
  • 13:12 - 13:16
    Okay, so this is basically what I wanted
    to say about password based KDFs. As I
  • 13:16 - 13:20
    said, this is not something you would
    build yourself. All crypto libraries have
  • 13:20 - 13:24
    an implementation of a PKCS#5
    mechanism. And you would just call the
  • 13:24 - 13:28
    appropriate function to convert a password
    into a key, and then use the resulting
  • 13:28 - 13:32
    key. Okay, in the next segment, we're
    gonna see how to use symmetric encryption
  • 13:32 - 13:35
    in a way that allows us to search on the
    cipher texts.
Title:
Key Derivation (14 min)
Video Language:
English

English subtitles

Revisions