RSA Public key Cryptography

advertisement
RSA Public key Cryptography
This is in many ways the jewel in the crown of number theoretic
cryptography. The idea here (envisaged first by Diffie and Hellman) was for
an encryption system with a public encryption key and a private decryption
key. In fact the idea is not outlandish at all- it is the precise analogue of a
padlock. Anyone can close a padlock - only the possessor of the key can open
it.
If you want to send me a secret, I send you an empty box and my open
padlock. You pop the secret in the box, put on the padlock and close it, and
send it back to me. I open it with my padlock key. As a manual way of
transmitting secrets, this is perfectly viable.
A padlock is a kind of one-way function - if you don’t have the key. Anyone
can squeeze it shut, but its virtually impossible to open. However possession
of the key acts as a kind of trap-door that springs it open instantly.
See what I’m getting at? A trap-door one-way function is what’s needed for
Public Key cryptography, and exponentiation modulo a carefully constructed
composite number is ideal for the purpose.
First I create my own padlock by generating two 512 bit prime numbers p and
q. I multiply them together to create a 1024 bit n. Now n is my padlock, p and
q together are my key.
(Note here that the padlock analogy breaks down in one significant way - it
costs nothing to make and distribute multiple copies of n).
To send me a message m, calculate and transmit m3 mod n. That’s the
message padlocked into a box. Only I, knowing p and q, can spring the lock,
by application of the secret “cube-rooting” exponent, calculated as 3-1 mod (p1)(q-1). Note that the message m could be itself a key, so RSA can be used for
secure key exchange as well.
A couple of important points about the practical implementation of RSA
 The primes p and q should be formed so that p-1 and q-1 are not smooth,
that is it does not have only small prime factors. One (perhaps extreme)
solution would be to make them both safe primes. This prevents a number
of attacks. In the past quite elaborate procedures were proposed for prime
generation, both to make factorisation of the modulus as difficult as
possible and to prevent various attacks. It was suggested at one time that
p+1 and q+1 should each have a large factor, as should [(p-1)/2]-1 and [(q1)/2]-1. These requirements are now known to be spurious. Furthermore
restrictions of this type introduce another danger, as if we are too picky
about the primes we choose, then an opponent, knowing our method, has
only a restricted set of primes to search among. In fact purely random
primes are probably as good as any, but a quick check that p-1 and q-1 are
not smooth is still recommended. For example if they can be fully factored
by trial division, then p and q are OK.
 The choice of 3 as an encryption exponent is not actually ideal, and causes
a few problems. For a start it is important that the “cubed” message suffers
modular reduction mod n, otherwise it may be recovered by simple integer
techniques. For example 23 mod n is 8, and the cube root of 8 is trivially 2.
Also if the same message is broadcast to three or more correspondents, then
an eavesdropper can reconstruct the actual value of m3 (not mod anything)
by application of the Chinese Remainder Theorem, and again find its
integer cube root, the message m. However any other (odd) encryption
exponent may be used. A small prime is good as it is more likely to have an
inverse mod (p-1)(q-1). The numbers 257 and 65537 are popular choices –
they are prime, big enough to avoid these attacks, and have a binary
representation with only two 1’s in it - which makes exponentiation more
efficient.
 The same message will always encrypt to the same ciphertext. This actually
leaks information - if someone observes the same ciphertext on two
different days, then they may not know what the message is, but they do
know that it is the same message as before. There are of course obvious
ways of disguising this - one could for example pad the message with
random data.
Program 3.2 - RSA
This program generates a prime pair and their product, and then encrypts and
decrypts a short “message”, using the RSA method. Note the use of the
Chinese remainder theorem to speed up decryption. Decryption is of course
carried out by the entity that knows the factors p and q, so this knowledge can
be used to advantage.
#include <iostream.h>
#include <stdlib.h>
#include "algor.h"
#define PBITS 14
// number of bits in p and q
void main()
{
Big p,q,n,phi,m,e,d,c,rp,rq;
// seed random number generator
srand(3);
e=257;
// encryption exponent
// generate two random primes
do
{
p=safe_prime(PBITS);
q=safe_prime(PBITS);
n=p*q;
phi=(p-1)*(q-1);
} while (gcd(e,phi)!=1);
d=inverse(e,phi);
// good parameters found - encrypt message
cout << "n= " << n << endl;
m=42;
cout << "Plaintext = " << m << endl;
c=pow(m,e,n);
cout << "Ciphertext = " << c << endl;
// Decrypt using CRT
rp=pow(c%p,d%(p-1),p);
rq=pow(c%q,d%(q-1),q);
m=crt(rp,p,rq,q);
cout << "Message = " << m << endl;
}
Small RSA Worked example.
Using exponent of 3, so p and q should both be 2 mod 3.
Choose p= 11 and q= 5, so n = 55
To encrypt the message 42,
C = 423 mod 55 = 3
To decrypt 3, using the Chinese remainder theorem, first find cube
roots of 3 mod 11 and mod 5.
1/3 mod 10 = 7 (cube-rooting exponent, 1/3 mod p-1)
1/3 mod 4 = 3
So
Mp = 37 mod 11 = 9 (cube root mod 11)
Mq = 33 mod 5 = 2
Apply CRT
c= 1/p mod q = 1/11 mod 5 = 1
t = 1*2 – 9 mod 5 = 3
M=3*11+9 = 42
Digital Signature, or Digital Sealing
The RSA system allows the concept of a Digital Signature.
Assume a scenario where Alice & Bob are in communication.
Now for Alice to ‘sign’ a plaintext, she first ‘decrypts’ or signs it with her
own private key, and then encrypts it with the Bob’s public key,.
1
3
C  [ P mod na ] mod nb
3
At the other end Bob reconstructs the plaintext by first decrypting with his
private key, hence stripping off the encryption, and then “encrypting” with
Alice’s public key to strip off the signature. (This is also called signature
verification.)
1
3
[C mod nb ] mod na  P
3
If P makes sense, then only Alice could have sent it, as only Alice knows her
private decryption key.
Note that a public key can be used for both encryption and the verification of
digital signature.
The private key can be used for both decryption and digital signature.
To Bob
Message
Alice Signs
message ….
…. and applies
Bob’s Public
key
However this is not quite as nice as it seems. How does Alice know that
Paddy hasn’t simply given me his public key, for which of course he has the
private key, and pretended that it is Bob’s? These keys are large numbers
that are difficult to remember. There is a need to securely associate a Public
key with its owner.
This is where Certification comes in. A certificate binds a public key to an
individual. A Trusted Third Party provides a certificate to each individual
involved. This consists of the users identity, other relevant information, and
their public key. The complete certificate is then in turn digitally signed by
the Trusted Third party, using their own public/private key pair. The TTP’s
public key is “well-known” to all parties.
So now to send you a message, I first sign the message with my own private
key. I then access your certificate from a public directory. I check the
validity of the certificate using the TTPs public key to verify the signature.
Then I encrypt the message using your public key as extracted from the
certificate.
When you receive the ciphertext, you decrypt it using your private key, and
then you verify my signature using my public key, which you get from my
certificate. Now you know it must have come from me, and authentication is
restored.
This certifies Bob:Name: Bob Ratcliff
Address: 4 Fred West Terrace
Height: 6’ 7
Hair Colour: Brown
This is his public key:-
Bob’s
Seal of Trusted
Authority
Now I can access Bob’s public key in such a way that I can trust that it really
is Bob’s public key. Further more I am also in a position to verify his seal, or
digital signature.
X.509 specifies a standard for certificate format.
Rabin’s method
This is a variant of RSA which uses the exponent 2. Unfortunately it has a
fatal Achilles heel - but nonetheless it is worthy of study. A message m is
encrypted by calculating m2 mod n, for n = pq, where p and q are typically
512 bit prime numbers.
The obvious disadvantage is that a ciphertext will have in general four square
roots, only one of which will correspond to the original message. But if this
were the only problem, it would not be insurmountable.
The good news is that cracking a cryptosystem based on this idea is provably
as difficult as factoring the modulus, because, as we have demonstrated, the
ability to extract a square root of an arbitrary number mod n can be exploited
to factor n. This is not the case with classic RSA - there may be a way of
extracting cube or higher roots without factoring the modulus (although this is
thought unlikely). Nevertheless on the face of it we can be more confident
with the security of this approach, because of its proven equivalence to the
difficulty of factoring.
The bad news is - it has a fatal flaw. The fact is that simply making use of the
decryption facility can reveal the factors of n. This is not true of RSA - I could
let an enemy use my decryption facility to extract cube roots to their hearts
content. This could not be exploited to factor my modulus. However such
access to a square-rooting facility allows just that. This is called a chosenciphertext attack. Simply encrypt any random message r, by squaring it mod
n and present it for decryption. Somehow get hold of the decrypt, and if it is
not r, then out pop the factors.
El Gamal Public Key Cryptography
This PK system is a little more elaborate than RSA. It is based on the
hardness of the discrete logarithm problem, rather than on integer
factorisation. It can be looked on as an extension of the Diffie-Hellman key
exchange algorithm.
Using the same p as used for Diffie-Hellman I generate a 1024 bit public key
y as
y = 3x mod p
I keep the 160 bit number x secret. To send me a message m, you generate a
random 160 bit number k, and perform the following calculations:-
c1 = 3k mod p
c2 = m.yk mod p
The data {c1,c2} is the ciphertext. The message m is effectively disguised in
c2 by being multiplied by a number that an outsider cannot determine.
However I, knowing x, can recover m as
m = c2/c1x mod p
This is easily verified by substituting for c1 and c2 from above.
An outsider must, it appears, solve the discrete logarithm problem in order to
break this system.
Observe that the ciphertext is twice the size of the message - this is
undoubtedly a disadvantage. But every cloud has a silver lining. Using this
method the same message will not now encrypt to the same ciphertext,
assuming it is associated each time with a different random value k.
#include <iostream.h>
#include <stdlib.h>
#include "algor.h"
#define PBITS 30
#define EBITS 12
void main()
{
Big p,c1,c2,m,k,pub,priv;
// seed random number generator
srand(4);
// generate PBITS-bit safe prime
p=safe_prime(PBITS);
cout << "Prime = " << p << endl;
// generate public/private key pair
priv=rand(EBITS,2);
pub=pow(3,priv,p);
m=42;
// encrypt message m
k=rand(EBITS,2);
c1=pow(3,k,p);
c2=modmult(m,pow(pub,k,p),p);
// decrypt message
m=modmult(c2,inverse(pow(c1,priv,p),p),p);
cout << "message= " << m << endl;
}
An alternative approach, which can also be used with the Diffie-Hellman key
exchange, is to use instead of a primitive root, a generator g of a large subgroup of order q, where q is a 160-bit prime that divides p-1. Such a g can be
easily found, as r(p-1)/q mod p, assuming r is a known primitive root. This
seems to be just as strong (although p is no longer “safe”). The modular
inversion can be profitably avoided in this case by decrypting m as
m = c2.c1 q-x mod p
#include <iostream.h>
#include <stdlib.h>
#include "algor.h"
#define QBITS 12
#define PBITS 30
void main()
{
Big p,q,m,t,g,c1,c2,priv,pub,k;
// seed random number generator
srand(5);
// generate QBITS bit prime q
q=rand(QBITS,2);
while (!prime(q)) q++;
cout << "sub-prime q= " << q << endl;
// find PBITS bit prime p = 2*m*q+1
t=pow(2,PBITS)/(2*q);
do
{
for (;;)
{
m=rand(t);
p=2*m*q+1;
if (prime(p)) break;
}
} while (digits(p,2)!=PBITS);
cout << "prime p= " << p << endl;
// get subgroup generator g
do { /* find primitive root t */
t=rand(p-1);
g=pow(t,(p-1)/q,p);
} while (g==1);
cout << "sub-group generator g= " << g << endl;
// generate public/private key pair
priv=rand(q);
pub=pow(g,priv,p);
cout << "Private key = " << priv << " Public Key = " <<
pub << endl;
m=42;
// encrypt message m
k=rand(q);
c1=pow(g,k,p);
c2=modmult(m,pow(pub,k,p),p);
// decrypt message
m=modmult(c2,pow(c1,q-priv,p),p);
cout << "message= " << m << endl;
}
Goldwasser-Micali
The difficulty of establishing quadratic residuosity with respect to a number
n=pq forms the basis of this public key method.
I generate n from two secret primes p and q, just as for the RSA method. I
make n public as well as a random quadratic non-residue y of n, constructed
such that (y/p) = (y/q) = -1. A QNR of this form is sometimes called a psuedo
QR, as (y/n) evaluates as +1.
To send me a message, break it down into individual bits, m0,m1,m2, etc.
Encrypt the i-th bit as follows:Generate a random xi < n
If mi = 0 send me ci = xi2 mod n.
If mi = 1 send me ci = y.xi2 mod n.
I alone can figure out the value of each bit, by checking whether or not the
received value is a truly a QR, by evaluating (ci/p). An outsider can of course
evaluate (ci/n), but this will always be +1, and so conveys no information.
Two points need to be made: This is not a practicable Public Key system, as, for typical security
parameters each message bit generates perhaps 1024 bits of ciphertext. This
is quite unacceptable.
 This is a probabilistic Public Key method. The same message will encrypt
differently each time, due to the random xi values associated with each bit.
This is an advantage with respect to RSA.
Although not a practicable system, it does illustrate the potential of the
exploiting quadratic residuosity.
Blum-Blum-Shub random number generator
What are the ideal properties of a pseudo-random number generator? In the
past various mathematical formulae have been suggested which appear to
generate random-looking numbers, and which have then been subjected to a
battery of arcane statistical tests, with names like the Poker test, the Chisquared test, the Kolmogorov-Smirnov test, etc.
In fact there is a way to short-circuit all of that. A good random number
generator that will pass all conceivable statistical tests need have just one
property – it should be unpredictable.
Consider now the simple iteration
x  x2 mod n
where n is the product of two 512-bit primes p and q, both congruent to 3 mod
4. In this case there is only one of the four square roots of a quadratic residue
that is itself a quadratic residue – the principle square root. So the series of
values generated by this iteration are uniquely defined in both directions – to
the right by squaring mod n, to the left by finding the unique principal square
root. In essence this iteration takes us on a random tour through the quadratic
residues. Consider now the sequence of bits generated by examining the least
significant bit of the value of x after each iteration, which might be, for
example
0 1 1 0 1 0 1 1 0 0 0 1 0 1 1 ……
Consider the predictability of this sequence, looked at initially backwards
from right to left. If I were able to predict the next bit to the left, then I would
be predicting the least significant bit of the square root of the current value of
x. And if I could do that then I could factor n. Therefore the unpredictability
of the bit sequence is nicely predicated on the difficulty of factoring n. Put
another way, if such bits could be predicted with accuracy any better than 5050, then it follows that factoring a 1024-bit number is easy. But it isn’t so,
well, draw your own conclusions. Unpredictability to the right depends on not
being able to guess the initial value of x, and if this is an unknown 1024-bit
value then this will clearly not be possible.
Example:
Consider n=437=19*23. Now 6 is a QR mod 437 and has 4 square roots 81,
356, 195 and 242. Of these 81 is the principal square root. Note that (81/19) =
(81 mod 19/19) = (5/19) = 59 mod 19 = +1. Also (81/23) = (12/23) = 1211 mod
23 = +1. Its principal square root is 9. The principal square root of 9 is 250….
etc.
x
x2
x
x2
x2
x
x2
x
1
1
2
4
3
9
4
16
5
25
6
36
7
49
8
64
9
81
13
17
21
25
29
169
289
4
188
404
10
14
18
22
26
30
100
196
324
47
239
26
11
15
19
23
27
31
121
225
361
92
292
87
12
16
20
24
28
32
144
256
400
139
347
150
33
37
41
45
49
53
57
61
65
69
73
77
215
58
370
277
216
187
190
225
292
391
85
248
34
38
42
46
50
54
58
62
66
70
74
78
282
133
16
368
315
294
305
348
423
93
232
403
35
39
43
47
51
55
59
63
67
71
75
79
351
210
101
24
416
403
422
36
119
234
381
123
36
422
40
44
48
52
56
60
64
68
72
76
80
289
188
119
82
77
104
163
254
377
95
282
81
6
85
89
93
97
101
105
109
113
233
55
346
232
150
100
82
96
82
86
90
94
98
102
106
110
114
169
404
234
96
427
353
311
301
323
83
87
91
95
99
103
107
111
115
334
140
415
285
187
121
87
85
115
84
88
92
96
100
104
108
112
116
64
315
161
39
386
328
302
308
346
117
121
125
129
133
137
141
145
149
153
157
161
165
169
173
177
181
185
189
193
197
201
205
142
220
330
35
209
415
216
49
351
248
177
138
131
156
213
302
423
139
324
104
353
197
73
118
122
126
130
134
138
142
146
150
154
158
162
166
170
174
178
182
186
190
194
198
202
206
377
26
144
294
39
253
62
340
213
118
55
24
25
58
123
220
349
73
266
54
311
163
47
119
177
123
127
131
135
139
143
147
151
155
159
163
167
171
175
179
183
187
191
195
199
203
207
271
397
118
308
93
347
196
77
427
372
349
358
399
35
140
277
9
210
6
271
131
23
120
124
128
132
136
140
144
148
152
156
160
164
168
172
176
180
184
188
192
196
200
204
208
416
81
215
381
142
372
197
54
380
301
254
239
256
305
386
62
207
384
156
397
233
101
1
209
213
217
221
225
418
358
330
334
210
214
218
222
400
348
328
340
211
215
219
223
384
340
328
348
212
216
220
224
370
334
330
358
370
226
230
234
238
242
246
384
23
131
271
6
210
227
231
235
239
243
247
400
47
163
311
54
266
228
232
236
240
244
248
418
73
197
353
104
324
251
255
259
263
267
271
275
279
283
287
291
295
299
303
307
311
315
319
323
327
331
335
339
343
347
351
355
359
363
367
73
349
220
123
58
25
24
55
118
213
340
62
253
39
294
144
26
377
323
301
311
353
427
96
234
404
169
403
232
93
252
256
260
264
268
272
276
280
284
288
292
296
300
304
308
312
316
320
324
328
332
336
340
344
348
352
356
360
364
368
139
423
302
213
156
131
138
177
248
351
49
216
415
209
35
330
220
142
96
82
100
150
232
346
55
233
6
248
85
391
371
375
379
383
387
391
395
399
403
407
411
415
419
423
348
305
294
315
368
16
133
282
26
239
47
324
372
376
380
384
388
392
396
400
404
408
412
416
420
292
225
190
187
216
277
370
58
215
404
188
4
289
423
427
431
435
196
100
36
4
424
428
432
436
169
81
25
1
229
233
237
241
245
1
101
233
397
156
249
253
257
261
265
269
273
277
281
285
289
293
297
301
305
309
313
317
321
325
329
333
337
341
345
349
353
357
361
365
384
207
62
386
305
256
239
254
301
380
54
197
372
142
381
215
81
416
346
308
302
328
386
39
161
315
64
282
95
377
250
9
254
258
262
266
270
274
278
282
286
290
294
298
302
306
310
314
318
322
326
330
334
338
342
346
350
354
358
362
366
277
140
35
399
358
349
372
427
77
196
347
93
308
118
397
271
177
115
85
87
121
187
285
415
140
334
123
381
234
369
373
377
381
385
389
393
397
401
405
409
413
417
254
163
104
77
82
119
188
289
422
150
347
139
400
370
119
374
378
382
386
390
394
398
402
406
410
414
418
36
422
403
416
24
101
210
351
87
292
92
361
421
425
429
433
256
144
64
16
422
225
426
430
434
121
49
9
Now start with x=250 and keep squaring and keep the least significant bit…
This random number generator obviously comes very close to the ideal of that
required by a one-time pad. Generate two suitable primes p and q and
multiply them to obtain n. Then destroy p and q - ideally this could all be
done inside a computer program which simply outputs n so that p and q are
never seen. To create a pseudo-one-time pad, distribute an initial value of x,
perhaps using the Diffie-Hellman method. Then XOR the least significant bit
of x after each iteration, with the next bit of the message. Breaking such a
system is provably equivalent to factoring a 1024-bit number, a task
considered at present to be completely computationally infeasible.
There are two potential shortcomings. First the method is rather inefficient –
each random bit produced requires a modular squaring of a 1024-bit number.
In fact it has been proved that up to lg (lg n) least significant bits can be
extracted simultaneously for use, without weakening the method. So if n is
1024 bits, then the 10 least significant bits can be used after each iteration – a
1000% improvement. In fact it has been conjectured that up to half the bits
can be safely used – but if we do so we loose our proof of equivalence with
factoring, which is the whole point of the method.
The second issue is that of cycle length. All deterministic pseudo-random
number generators start to repeat eventually. However it turns out that if the
values of x generated by repeated modular squaring mod n start to cycle, then
this cycling could be easily exploited to factor n. So, based on our working
assumption that factoring is hard, we can further assume that cycling will
never occur.
Program 3.5 – Blum-Blum-Shub pseudo random number generator
#include <iostream.h>
#include <stdlib.h>
#include "algor.h"
#define PBITS 14
void main()
{
Big x,p,q,n;
// seed random number generator
srand(5);
// generate two PBITS-bit safe primes
p=safe_prime(PBITS);
q=safe_prime(PBITS);
n=p*q;
p=0; q=0;
// destroy p and q
x=rand(2*PBITS,2);
for (int i=0;i<70;i++)
{
x=modmult(x,x,n);
cout << (x&1);
// output least significant bit
}
}
Blum-Goldwasser PK system
The Blum-Blum-Shub cryptographically strong number random number
generator can be converted into a Public Key Method. The initial set-up is
similar to RSA. A public key n is formed as the product of two primes p and
q, this time both congruent to 3 mod 4. The composite n constitutes the public
key, and the two prime factors are the private key. The idea is now quite
simple. To send me a message, generate a random initial value for x, and start
squaring it mod my public key n. Use the resulting BBS generator as a onetime pad to encrypt the message. Then send me
 The encrypted message
 The length of the message m
 The final value of xm, after one last squaring mod n.
To reconstruct the message, I can use my secret knowledge of p and q to
“rewind” the one time-pad to its beginning, and run it again over the
ciphertext, thus revealing the message. Specifically I can use my knowledge
of p and q to calculate repeated square roots of the final value of x, until it has
the same value it had initially. I can now run the pad forward again to decrypt
the message.
If the message consisted of m bits (assuming only the least significant bit of x
is being used for encryption), then I must rewind the generator back m steps.
One way would be to find m square roots, one after the other. But in fact I can
jump straight back to the beginning in just one step, and as I know p and q the
Chinese remainder theorem is relevant.
Calculate
x p  xm
[( p 1) / 4 ]m mod p 1
mod p
Next calculate xq in a similar fashion, and combine the values of xp and xq
using the CRT. The value obtained is the initial value of x used to encrypt the
message. After this complex initial calculation, things proceed very much as
for encryption. The pad is run forward again over the ciphertext, in effect
stripping off the encryption and revealing the original message.
As a PK system, this method is in many ways superior to RSA. In particular it
is far more efficient in terms of bits encrypted per second, particularly if used
to encrypt a very long message. It is, like the impractical Goldwasser-Micali
method a naturally probabilistic PK system, as the same message will not
encrypt to the same ciphertext, due to the encryptor’s random initial choice of
x.
There is however, sadly, a fly in the ointment. Since the decrypting process
now has the capacity to calculate square roots mod n, it can be abused to
reveal the factors of n – using basically the same chosen ciphertext attack that
rendered the Rabin method vulnerable. Note that this attack is possible even
though the decrypting process might reveal only a few bits of a square roots at
a time – recall that the ability to consistently determine even a bit of a square
root can, by repeated invocation, be used to factor n. 1
So it turns out again that a method based on the difficulty of extracting square
roots and hence equivalent to factoring the modulus, falls again to a chosen
ciphertext attack, which turns this apparent strength into a weakness.
This flaw does not affect the security of the BBS generator, for which of course
no decrypting process exists. In that case, since p and q have been destroyed, any
technique that recovers them constitutes a bone fide factoring algorithm.
1
We can however fix things, after a fashion. Choose p and q now to be
congruent to 2 mod 3, and replace the basic BBS iteration with
x  x3 mod n
This works just as well, except that its security now depends, not on the
difficulty of factoring, but rather on an instance of the weaker RSA
assumption, that is the difficulty of extracting cube roots mod n without
knowledge of the factors of n. Again the lg( lg n) least significant bits are
simultaneously secure (under this assumption).
Encryption proceeds as before, using this new iteration. To rewind this
generator prior to decryption calculate
x p  xm
[( 2 ( p 1) 1) / 3]m mod p 1
mod p
And similarly xq.
Combining these values via the CRT gives the same value of x as could have
been obtained (less efficiently) by serially extracting m cube roots of the final
value of x that comes with the encrypted message.
Now we finally have a perfectly viable probabilistic PK system. It hasn’t
proved as popular as RSA for a number of reasons: Its improved efficiency is not relevant in most applications, where only
only a short message is to be encrypted.
 It encrypts as a stream cipher using simple XOR. This is vulnerable to a
substitution attack. Classic RSA encrypts as a block cipher.
#include <iostream.h>
#include <stdlib.h>
#include "algor.h"
#define PBITS 14
char message[]="This is a test of the Blum-Goldwasser
probabalistic PK system";
void main()
{
int i,m;
Big x,p,q,n,xp,xq,e;
// seed random number generator
srand(54);
// generate two PBITS-bit safe primes
p=safe_prime(PBITS);
q=safe_prime(PBITS);
n=p*q;
// encrypt message
x=rand(PBITS,2);
// random x
for (m=0;message[m]!=0;m++)
{
x=pow(x,3,n);
message[m]^=(char)x;
// XOR with least
// significant byte of x
}
cout << "Ciphertext= \n" << message << endl;
x=pow(x,3,n);
// once more
// decrypt message
// first recover pad
e=pow((2*(p-1)+1)/3,m+1,p-1);
xp=pow(x,e,p);
e=pow((2*(q-1)+1)/3,m+1,q-1);
xq=pow(x,e,q);
x=crt(xp,p,xq,q);
// combine with CRT
for (i=0;i<m;i++)
{
x=pow(x,3,n);
message[i]^=(char)x;
// XOR with least
// significant byte of x
}
cout << "Message= \n" << message << endl;
}
Download