Introduction to Public Key Cryptography

advertisement
Introduction to Public Key Cryptography
Background
The problem with symmetric or secret key cryptography is keeping the secret key secret.
If some nefarious person gets your secret key, it’s like the guy said in the movie, Aliens,
“Game over, man! Game over!” The biggest problem with secret key cryptography is
distributing the key. Wouldn’t it be great to have a system so that you could send secret
messages without having to send secret keys back and forth? Wouldn’t it be great if you
could send and receive secret messages to people you hadn’t met yet?
This sounds like the Holy Grail of Cryptography. It also sounds impossible. If you were
to quiz the world’s cryptographers in 1975, if this could be done someday, they would
have said told you it was impossible. Imagine everyone’s surprise in 1976, when
Whitfield Diffie and Martin Hellman sprung asymmetric or public key cryptography on
the world! To be fair, James Ellis, Clifford Cocks, and M.J. Williamson of British
Intelligence discovered the same thing a few years earlier, but they didn’t do anything
with it. Of course, the NSA claims they knew about it first.
The basic idea of the public key cryptography is that it’s easy to do a mathematical
function in one direction and very difficult to do it in reverse. Multiplication and
factoring are good examples. It’s easy to multiply two large prime numbers together but
given the product, it’s difficult to say what the original two numbers were that produced
the product. This is the kind of math used to make public cryptography work; it involves
multiplication, modular arithmetic, and exponentiation.
Instead of a single key, there are now two keys, one used to encrypt and the other used to
decrypt. The keys are different and it is not possible to compute one from the other. That
means, just because you have the encryption key, you can’t figure out what the
decryption key is.
Here’s the great part about this: I can create pair of these keys. I can put the encryption
key on my website, my business cards, in my e-mail signature. I can give it to my friends;
they can give it to their friends. Somebody I’ve never met can send me email encrypted
with my public key. Then this person can send me the email. I take my decryption key
(which I do not reveal) and decrypt the message. The sender of the email and I did not
have to go thru all sorts of covert contortions to keep keys secret.
Dramatis Personae
The players in tonight’s drama are Alice, Bob, and Eve. Alice and Bob want to carry on
an exchange of information in an encrypted manner. Eve is a nefarious person interested
in finding out what information Alice and Bob are carrying on.
The Mathematics
Communicating "in the clear", Alice and Bob select two numbers, q and n. Alice then
selects the secret number xa. Bob selects the secret number xb. From the two public
numbers, q and n, and her secret number xa, Alice calculates ya and sends the number to
Bob. Using the same two public numbers, q and n, and his secret number xb, Bob
calculates yb and sends the number to Alice. Alice and Bob have completed step one of
the Diffie-Hellman process.
The program crypto.bc shows how Alice calculates ya using the formula
ya = (n ^ xa) % q
This says, multiply n by itself xa times, then divide the product by q and save only the
remainder.
Alice sends the number ya to Bob. In the meantime, Bob applies the same formula to the
numbers n, xb and q to calculate the number yb:
yb = (n ^ xb) % q
Bob sends the number yb to Alice. They are ready for step two.
Using the number yb received from Bob, Alice calculates
ka = (yb ^ xa) % q
Again, this means multiply yb by itself xa times, and then save the remainder after
dividing the product by q. When Bob receives Alice's number ya he calculates:
kb = (ya ^ xb) % q
Alice and Bob have completed the Diffie-Hellman encryption process.
The Magic
Alice applied her secret number xa to Bob's value yb and calculated ka. Bob applied his
secret number xb to Alice's value ya and calculated kb. Presto: it turns out that ka = kb,
a number now known to Alice and Bob, but to no one else. Even though Eve, the
eavesdropper, may have been monitoring their communications studiously, Eve cannot
discover the number ka easily.
The Diffie-Hellman Algorithm
The crypto.bc program, written for the bc compiler, was adapted from Simson Garfinkel's
book on Phil Zimmerman's Pretty Good Privacy. Where large numbers would be used in
practice, we use small numbers for clarity. The operation x % y returns x modulo y, that
is, the remainder obtained when x is divided by y. The operation n ^ xa multiplies the
number n times itself xa times. In programs designed to handle really large numbers, we
can speed up the calculation of (n ^ xa) % q by applying the modulo operation after each
multiply. While using relatively small numbers, illustration is made simpler.
When executed with the command bc crypto.bc, this program writes the following output
to stdout:
Alice sends ya = 78 to Bob
Bob sends yb = 534 to Alice
from yb^xa = 3530785328217308860798464
Alice calculates ka = 117
from ya^xb = 308549209196654470906527744
Bob calculates kb = 117
They can now use 117 to encrypt messages.
Passing Secrets
Operating completely in the clear, Alice and Bob have passed the number 117 between
them without disclosing it to anyone else. Eve, who may have been monitoring their
communications or recording them for analysis, may have difficulty discovering the
number ka = 117.
Eve knows the numbers n, q, ya and yb, so she could write the equation
ya = ( n ^ xa) % q
and try all possible values of xa until she finds one that generates the known value of ya.
Using that value of xa in the equation
ka = (yb ^ xa) % q
Eve could calculate the value of ka. This "brute force" method of attack, however, is
practical only if Alice and Bob use small numbers. By using large numbers, preferably
large prime numbers, Alice and Bob can make Eve's brute force attack impractical.
Of Prime (Number) Importance
We need prime numbers for the Diffie-Hellman process. To find prime numbers, we can
use the program, testprime2.bc to find large prime numbers. The program first asks for a
starting value. It tests the number entered, then loops repeatedly asking for an increment,
advancing the test value by that amount and then testing again. Here is an example
interaction:
enter a starting value, then increments (or 0 to quit):
123487 is not prime, smallest factor is 7
2
123489 is not prime, smallest factor is 3
2
123491 is a prime number
We need two prime numbers, so call the program again:
enter a starting value, then increments (or 0 to quit):
394323 is not prime, smallest factor is 3
2
394325 is not prime, smallest factor is 5
2
394327 is a prime number
Alice and Bob now have prime numbers to use. Alice has a program, alice.bc, and Bob
has bob.bc to calculate keys using the Diffie-Hellman algorithm.
Trying It Out
Alice selects a secret number, such as 76697, and calls her program. Her interactive
session looks like this:
Alice:
Enter public value q: 394327
Enter public value n: 123493
Enter your secret number xa: 76697
Alice, here is the number to send to Bob, ya: 323823
Bob selects the secret number 69623. His interactive session looks like this:
Bob:
Enter public value q: 394327
Enter public value n: 123493
Enter your secret number xb: 69623
Bob, here is the number to send to Alice, yb: 32675
Enter the number received from Alice, ya: 323823
Result: 74297
Bob has completed his side of the Diffie-Hellman process.
When Alice receives the number yb from Bob, she cam complete the process on her side:
Enter the number you received from Bob, yb: 32675
Result: 74297
Alice and Bob each have slipped the number 74297 past Eve, and they now can use that
number to generate a key for encrypting messages.
Eve Strikes
Eve, of course, has been watching all this and has written a program of her own.
When Eve calls her program eve.bc, her interactive session looks like this:
Eve:
enter public value q: 394327
enter public value n: 123493
enter observed public number ya: 323823
enter observed public number yb: 32675
enter a starting value for xa: 2
trying 3
trying 4
trying 5
trying 6
trying 7
<snip>
trying 76693
trying 76694
trying 76695
trying 76696
trying 76697
found xa = 76697
Result: 74297
Depending on the speed of Eve's computer, this may take several minutes.
Selecting q and n
When selecting two prime numbers for the Diffie-Hellman process, use the larger number
for q and the smaller number for n. To discover why, try swapping the two numbers
around. With the values of q and n swapped, that is, with n larger than q, while Alice and
Bob may see nothing out of the ordinary, Eve's cryptanalysis becomes much easier.
And there is more. In addition to q being a prime number, the value (q-1)/2 should also
be a prime number. This makes it harder for Eve to work backwards to the value of xa.
Use the program, testqm1.bc to find prime numbers that fit this criteria. An example
session looks like:
enter a starting value, then state how many primes to find:
2426697105
3
q = 2426697107 is prime and (q-1)/2 = 1213348553 is ALSO prime
q = 2426697359 is prime and (q-1)/2 = 1213348679 is ALSO prime
q = 2426698727 is prime and (q-1)/2 = 1213349363 is ALSO prime
Size Does Matter
Knowing all of this, Alice selects 2426697107 for q and calls the testqm1 program again
to find a smaller prime to use for n:
enter a starting value, then state how many primes to find:
17123201
2
q = 17123207 is prime and (q-1)/2 = 8561603 is ALSO prime
q = 17124539 is prime and (q-1)/2 = 8562269 is ALSO prime
Alice selects 17123207 for n. With these numbers, and selecting the arbitrary number
31925631 for xa, Alice's interactive session looks like:
Alice:
Enter public value q: 2426697107
Enter public value n: 17123207
Enter your secret number xa: 31925631
Alice, here is the number to send to Bob, ya: 919478360
Alice sends the numbers q, n and ya to Bob. Using his selected secret number 19758139,
Bob's interactive session looks like:
Bob:
Enter public value q: 2426697107
Enter public value n: 17123207
Enter your secret number xb: 19758139
Bob, here is the number to send to Alice, yb: 1724324231
Enter the number received from Alice, ya: 919478360
Result: 1490225501
When Alice receives Bob's number yb, she completes her calculation:
Enter the number you received from Bob, yb: 1724324231
Result: 1490225501
Eve Strikes Back
Eve calls her program
Eve:
enter public value q: 2426697107
enter public value n: 17123207
enter observed public number ya: 919478360
enter observed public number yb: 1724324231
enter a starting value for xa: 2
trying 3
trying 4
trying 5
trying 6
trying 7
...
<snip>
Eve's program found xa = 31925631 and the result = 1490225501. On a 866 MHz
Pentium Xeon with 1GB of memory and 1723.59 BogoMIPS, it took 9 hours to do the
calculation.
If Eve is on a network where she has access to, say, 30 other similar systems, she could
run 30 copies of her program simultaneously; starting the first program near 0, the second
at 1000000, the third at 2000000 and so on. One of the computers should find the solution
within about 30 minutes. That being the case, perhaps Alice and Bob should use numbers
even larger.
Picking Secret Numbers
Because it is xa that Eve's program must find, it might appear that simply selecting a very
large value for xa would defeat Eve's brute force attack. The reality, though, is exactly
the opposite. For the values
q = 394327
n = 123493
xa = 76697
xb = 59232
Alice and Bob found result 365557. Eve's program found the same xa = 77797 and result
= 365557 in about three minutes. For the same values of q and n with the larger values
xa = 766973423
xb = 592329871
Alice and Bob obtained the result = 32000. In only eight seconds, Eve's program found
this same result at a test value of xa = 9353. So it seems that if xa has more digits than q,
then Eve's program doesn't even need to discover Alice's secret number xa at all. Instead
it can find a solution at the much smaller trial value of xa. Modulo arithmetic is like a
rain in Texas – you can’t be sure where it’s going to fall.
Resources
GNU Privacy Guard, a free replacement for PGP, can be downloaded from
www.gnupg.org.
Also available from the Free Software Foundation is the GNU bc compiler written by
Philip A. Nelson. The entire bc package, including sources, can be downloaded from
www.gnu.org/ directory/bc.html.
An introduction to Pretty Good Privacy, including a blow-by-blow account of Phil
Zimmerman's many battles, can be found in the book PGP: Pretty Good Privacy, by
Simson Garfinkel, published in 1995 by O'Reilly. ISBN 1-56592-098-8.
For additional background on PGP, see Phil Zimmerman's own book, The Official PGP
User's Guide, published in 1995 by The MIT Press.
For background on cryptography in practice that is written by a professional in the field,
with details on Diffie-Hellman, RSA and many other algorithms, find a copy of Bruce
Schneier's Applied Cryptography, published by Wiley. The second edition is available on
Amazon.
Programs
Testprime2.bc
/* testprime2.bc: test for prime numbers
The exhaustive search method used here
works ok for numbers up to about 12 digits.
*/
define qprime(value) {
auto d, rem
small_factor = 2
rem = value % 2
if ( rem == 0 ) return(rem) # it is even
small_factor = 3
if ( value == 9) return(0) # skip it so we can start at 3
for (d = 3; d^2 <= value; d += 2) {
rem = value % d
/*
print "d = ",d
print "rem = ",rem
print "\n"
*/
if ( rem == 0 ) break
}
small_factor = d
return(rem)
}
scale = 0
print "enter a starting value, then increments (or 0 to quit):\n"
testvalue = read();
/* get the starting value */
while ( 1 ) {
a = qprime(testvalue)
print testvalue
if ( a == 0 && testvalue != 2 ) {
print " is not prime, smallest factor is ",small_factor
}
if ( a != 0 ) {
print " is a prime number"
}
if ( testvalue == 2 ) {
print " is a special case, Ducky"
}
print "\n"
increment = read()
if (increment == 0) { break }
testvalue += increment
}
halt
Alice.bc
/* alice.bc: Diffie-Hellman encryption demo
*/
# this modexp() bc routine is a transliteration
# of the C routine found in Bruce Schneier's
# "Applied Cryptography" Wiley, New York. 1994.
# ISBN 0-471-59756-2
# modexp: from page 200
define modexp(a, x, n) { # return a ^ x mod n
auto r
r=1
while ( x > 0 ) {
if ( (x % 2) == 1 ) {
r = (r * a) % n
}
a=(a*a)%n
x /= 2
}
return(r)
}
print "Alice:\n"
print "Enter public value q: "; q = read()
print "Enter public value n: "; n = read()
print "\nEnter your secret number xa: "; xa = read()
ya = modexp(n,xa,q)
print "\nAlice, here is the number to send to Bob, ya: "; ya
print "\nEnter the number you received from Bob, yb: "; yb = read()
ka = modexp(yb,xa,q)
print "Result: "; ka
print "\n\n"
halt
Bob.bc
/* bob.bc: Diffie-Hellman encryption demo for Bob
*/
# this modexp() bc routine is a transliteration
# of the C routine found in Bruce Schneier's
# "Applied Cryptography" Wiley, New York. 1994.
# ISBN 0-471-59756-2
# modexp: from page 200
define modexp(a, x, n) { # return a ^ x mod n
auto r
r=1
while ( x > 0 ) {
if ( (x % 2) == 1 ) {
r = (r * a) % n
}
a=(a*a)%n
x /= 2
}
return(r)
}
print "Bob:\n"
print "Enter public value q: "; q = read()
print "Enter public value n: "; n = read()
print "\nEnter your secret number xb: "; xb = read()
yb = modexp(n,xb,q)
print "\nBob, here is the number to send to Alice, yb: "; yb
print "\nEnter the number received from Alice, ya: "; ya = read()
kb = modexp(ya,xb,q)
print "\nResult: "; kb
print "\n\n"
halt
eve.bc
/*
* eve.bc: Brute force attack on Diffie-Hellman encryption
*/
define modexp(a, x, n) { # return a ^ x mod n
auto r
r=1
while ( x > 0 ) {
if ( (x % 2) == 1 ) {
r = (r * a) % n
}
a=(a*a)%n
x /= 2
}
return(r)
}
print "Eve:\n"
print "enter public value q: "; q = read()
print "enter public value n: "; n = read()
#print "\nenter your secret number x: "; xa = read()
print "\nenter observed public number ya: "; ya = read()
print "\nenter observed public number yb: "; yb = read()
print "\nenter a starting value for xa: "; xa = read()
while ( 1 ) {
tya = modexp(n,xa,q)
if (tya == ya) { break }
xa += 1
print "trying ", xa, "\n"
}
print "\nfound xa = "; xa
ka = modexp(yb,xa,q)
print "\nResult: "; ka
quit
testqm1.bc
/*
testqm1.bc: find prime number q and test (q-1)/2 also.
The exhaustive search method used here
works ok for numbers up to about 12 digits.
*/
define qprime(value) {
auto d, rem
small_factor = 2
rem = value % 2
if ( rem == 0 ) return(rem) # it is even
small_factor = 3
if ( value == 9) return(0) # skip it so we can start at 3
for (d = 3; d^2 <= value; d += 2) {
rem = value % d
if ( rem == 0 ) break
}
small_factor = d
return(rem)
}
scale = 0
print "enter a starting value, then state how many primes to find:\n"
testvalue = read()
/* get the starting value */
find = read()
/* get the count of primes to find */
i = 0; increment = 2
while ( i < find ) {
a = qprime(testvalue)
if ( a != 0 ) {
savetest = testvalue
t = (testvalue - 1)/2
aa = qprime(t)
if ( aa != 0 ) {
print "q = ", testvalue
print " is prime and (q-1)/2 = ", t
print " is ALSO prime\n"
i += 1
}
}
if ( testvalue == 2 ) {
print testvalue
print " is a special case, Ducky\n"
testvalue += 1
}
testvalue += increment
}
halt
Download