Public key cryptography is a critical part
of many secure systems today.
It’s different than symmetric cryptography
in that there’s what’s called a “public”
key, a key that doesn’t have to be secret.
You can distribute this public key freely
and still communicate securely.
So how does that work?
Like symmetric cryptography, public key ciphers
have three algorithms, one to generate keys,
one to encrypt, and one to decrypt.
But they differ it two major ways.
First, the generate algorithm generates *two*
keys, a public key K and a private key K-
inverse.
To encrypt, you pass the public key and a
plaintext to obtain a ciphertext.
To decrypt, you pass the private key and the
ciphertext to obtain the plaintext.
Therefore, if you generate the keys, you can
give out the public key freely, hence its
name, and know that only someone with the
private key and decrypt something sent with
the public key.
Because the public key is reused many times,
this means the encryption process has to include
randomization.
Otherwise, two parties that send the same
message will produce the same ciphertext.
If you’re dealing with small messages, and
adversary could just exhaustively try all
of the messages.
So, for example, you can prepend some random
data to the plaintext to generate the ciphertext.
So this is kind of magic: you can generate
two keys, one public, one private.
People with the public key can then send data
only someone with the private key can decrypt.
If each side had the other’s public key,
we wouldn’t need symmetric cryptography
at all!
It turns out that’s not the case, as I’ll
explain in a little bit.
Public key cryptography is much, much computationally
expensive than symmetric cryptography.
So we can’t just use it all the time.
You can use public key cryptography for integrity
as well, using something called a signature.
Again, we have three functions: generate,
which generates a pair of keys, sign, which
takes the private key, and verify, which takes
the public key.
A signature provides integrity like a MAC.
You can’t produce a valid signature for
a message m without the private key, but anyone
can verify it with the public key.
Furthermore, you can’t derive the public
key from the private one.
There are a lot of public key algorithms out
there.
For encryption, we have RSA, Rabin, and ElGamal.
For signatures, we have RSA, Rabin, ElGamal,
and DSA.
But public key algorithms work differently
than symmetric ones.
The basic idea behind RSA, for example, is
really simple: modular exponentiation of large
integers.
However, simple transformations of a message
to a number is not secure.
So you have to be careful in how you use them.
I gave one example of that earlier, how you
have to add randomness.
So, generally speaking, it’s good to use
existing, tested implementations of these
algorithms rather than try to re-implement
them yourself.
Or you can re-implement them, but then don’t
use your implementation in a secure system.
For many of these algorithms, you can use
the same key for encryption and signing.
While they use the same key, though, they
use different algorithms.
You can’t, for example, sign a document
by “encrypting” it with the private key.
I’m not going to go into all of the details,
but I want to give you a sense of how one
very famous of these algorithms, RSA, works.
RSA is named for its co-creators, Rivest,
Shamir, and Adleman.
They won a Turing award, the highest award
in computing, for it.
I’m presenting RSA because conceptually
it’s very simple.
To generate RSA keys, you choose to distinct,
very large, prime numbers p and q.
From p and q you compute their product, n.
You then use p and q to derive K and K-inverse.
You advertise n and K as the public key.
To encrypt a message, you consider the message
M as a large number and raise it to the K
power, then take it modulo n.
You send that ciphertext number.
To decrypt, you consider the ciphertext message
M as a large number and raise it to the K-inverse
power, then take it modulo n.
It turns out that if you do this, you will
recover the original plaintext message.
So you derive K and K-inverse from p and q.
If an adversary learns p and q, then they
can generate the private key and break the
system.
You can’t derive p and q from K.
It turns out you also can’t derive p and
q from n.
N is the product of two primes.
Factoring n into p and q turns out to be computationally
hard.
If someone figured out how to do it quickly,
all of RSA crashes down.
As you can imagine, a lot of people have put
a huge amount of effort into understanding
how hard it is to factor a product of two
prime numbers.
For those of you who know a bit about computational
complexity, we know that the problem is in
the computational class NP, it’s suspected
to be outside the class P, but it’s suspected
to not be NP- complete.
So that means our best guess is that you can’t
do it in polynomial time, but it’s not as
hard as the hardest problems in NP, like traveling
salesman.
So public key cryptography seems pretty amazing.
You can generate two keys, distribute one
publicly, and then have confidentiality, integrity,
and authenticity.
Why do we use symmetric cryptography at all?
There is, of course, a catch.
Public key cryptography is much, much slower
than symmetric ciphers.
We can do symmetric crypto at line rate.
Public key systems, though, have execution
times in milliseconds.
For example, if you run RSA with a 2048-bit
key,it takes nearly 6 milliseconds to decrypt
a message.
And remember, the party who has the private
key does the decrypting.
So if you distribute your public key widely
so lots of other parties can communicate with
you, you’re the bottleneck on how many messages
can be handled.
So this is why hybrid schemes are very popular
today.
The idea is that you start with public key
cryptography, and use it to encrypt a symmetric
key.
Or you use it to exchange some information,
a secret session key, that you use to generate
symmetric keys.
You bootstrap the secure session with public
key cryptography to exchange a secret, then
use that secret for much more efficient symmetric
cryptography.
If you want to see a detailed example of this,
I’ll cover one in the TLS video.
Now, one big pitfall people often run into
with public key cryptography is signing an
underspecified message.
For example, if I sign a message, I should
specify whom the message is for.
And give it a lifetime.
Otherwise, someone can simply replay the message.
Since my public key doesn’t change very
often, a signed message is valid as long as
people are using my public key.
By valid, I mean it will properly pass the
verify function.
So you want to limit its use at the application
level.
Otherwise a signed message saying “You can
access this file” could be taken by an adversary
and used.
Instead, you should say “Nick can access
this file until noon on Halloween.”
