1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
|
// Build don't link:
// Special g++ Options: -fexceptions
// testcase to check obstack allocation for cleanups
typedef unsigned char byte;
typedef unsigned short word16;
typedef unsigned long word32;
typedef unsigned char boolean;
enum {FALSE, TRUE};
extern "C" {
extern void __eprintf (const char *, const char *, unsigned, const char *);
}
extern "C" {
typedef unsigned int size_t;
extern void *memccpy(void *, const void *, int, size_t);
extern void *memchr(const void *, int, size_t);
extern void *memset(void *, int, size_t);
}
template <class T> struct SecBlock
{
public:
SecBlock(unsigned int size)
: size(size), ptr((new T [( size )]) ) {}
~SecBlock()
{(memset(( ptr ), 0, ( size )*sizeof(*( ptr ))), delete [] ( ptr )) ;}
operator T *() const
{return ptr;}
T *operator +(unsigned int offset)
{return ptr+offset;}
T& operator[](int index)
{((void) (( index<size ) ? 0 : (__eprintf ("%s:%u: failed assertion `%s'\n", "misc.h" , 31 , "index<size" ), 0) )) ; return ptr[index];}
const T& operator[](int index) const
{((void) (( index<size ) ? 0 : (__eprintf ("%s:%u: failed assertion `%s'\n", "misc.h" , 33 , "index<size" ), 0) )) ; return ptr[index];}
const unsigned int size;
T *const ptr;
};
typedef SecBlock<byte> SecByteBlock;
void xorbuf(byte *buf, const byte *mask, unsigned int count);
void byteReverse(word16 *out, const word16 *in, unsigned int byteCount);
void byteReverse(word32 *out, const word32 *in, unsigned int byteCount);
inline word16 Invert(const word16 value)
{
return (value << 8) | (value >> 8);
}
inline word32 Invert(const word32 value)
{
word32 work = ((value & 0xFF00FF00L) >> 8) | ((value & 0x00FF00FFL) << 8);
return (work << 16) | (work >> 16);
}
template <class T> inline T min (const T t1, const T t2)
{
return (t1 < t2 ? t1 : t2);
}
template <class T> inline T max (const T t1, const T t2)
{
return (t1 > t2 ? t1 : t2);
}
template <class T> inline void swap (T &a, T &b)
{
T temp = a;
a = b;
b = temp;
}
template <class T> inline T rotl(T x, unsigned int y)
{
return ((x<<y) | (x>>(sizeof(T)*8-y)));
}
template <class T> inline T rotr(T x, unsigned int y)
{
return ((x>>y) | (x<<(sizeof(T)*8-y)));
}
int BytePrecision(unsigned long);
int BitPrecision(unsigned long);
unsigned long Crop(unsigned long, int size);
enum CipherDir {ENCRYPTION, DECRYPTION};
class BlockTransformation
{
public:
virtual ~BlockTransformation() {}
virtual void ProcessBlock(byte *inoutBlock) =0;
virtual void ProcessBlock(const byte *inBlock, byte *outBlock) =0;
virtual unsigned int BlockSize() const =0;
};
class StreamCipher
{
public:
virtual ~StreamCipher() {}
virtual byte ProcessByte(byte input) =0;
virtual void ProcessString(byte *outString, const byte *inString, unsigned int length);
virtual void ProcessString(byte *inoutString, unsigned int length);
};
class RandomAccessStreamCipher : public StreamCipher
{
public:
virtual ~RandomAccessStreamCipher() {}
virtual void Seek(unsigned long position) =0;
};
class RandomNumberGenerator
{
public:
virtual ~RandomNumberGenerator() {}
virtual byte GetByte() =0;
virtual int GetBit();
virtual word32 GetLong(word32 min=0, word32 max=0xffffffffL);
virtual word16 GetShort(word16 min=0, word16 max=0xffff)
{return (word16)GetLong(min, max);}
virtual void GetBlock(byte *output, unsigned int size);
};
template <class T> void Shuffle(RandomNumberGenerator &rng, T *array, unsigned int size)
{
while (--size)
swap(array[size], array[(unsigned int)rng.GetLong(0, size)]);
}
class HashModule
{
public:
virtual ~HashModule() {}
virtual void Update(const byte *input, unsigned int length) =0;
virtual void Final(byte *digest) =0;
virtual int DigestSize() const =0;
virtual void CalculateDigest(byte *digest, const byte *input, int length)
{Update(input, length); Final(digest);}
};
class BufferedTransformation
{
public:
virtual ~BufferedTransformation() {}
virtual unsigned long MaxRetrieveable() =0;
virtual void TransferTo(BufferedTransformation &target);
virtual boolean Attachable() {return FALSE;}
virtual void Detach(BufferedTransformation *) {}
virtual void Attach(BufferedTransformation *) {}
virtual void Close() {InputFinished();}
virtual void Put(byte inByte) =0;
virtual void Put(const byte *inString, unsigned int length) =0;
virtual void InputFinished() {}
void PutShort(word16 value, boolean highFirst=TRUE);
void PutLong(word32 value, boolean highFirst=TRUE);
virtual int Get(byte &outByte) =0;
virtual unsigned int Get(byte *outString, unsigned int getMax) =0;
int GetShort(word16 &value, boolean highFirst=TRUE);
int GetLong(word32 &value, boolean highFirst=TRUE);
unsigned int Skip(unsigned int skipMax);
};
class PK_CryptoSystem
{
public:
virtual ~PK_CryptoSystem() {};
virtual unsigned int MaxPlainTextLength() const =0;
virtual unsigned int CipherTextLength() const =0;
};
class PK_Encryptor : public PK_CryptoSystem
{
public:
virtual void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText) =0;
};
class PK_Decryptor : public PK_CryptoSystem
{
public:
virtual unsigned int Decrypt(const byte *cipherText, byte *plainText) =0;
};
class PK_SignatureSystem
{
public:
virtual ~PK_SignatureSystem() {};
virtual unsigned int MaxMessageLength() const =0;
virtual unsigned int SignatureLength() const =0;
};
class PK_Signer : public PK_SignatureSystem
{
public:
virtual void Sign(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) =0;
};
class PK_Verifier : public PK_SignatureSystem
{
public:
virtual boolean Verify(const byte *message, unsigned int messageLen, const byte *signature) =0;
};
class ByteQueueNode;
class ByteQueue : public BufferedTransformation
{
public:
ByteQueue();
~ByteQueue();
unsigned long CurrentSize() const;
unsigned long MaxRetrieveable()
{return CurrentSize();}
void Put(byte inByte);
void Put(const byte *inString, unsigned int length);
int Get(byte &outByte);
unsigned int Get(byte *outString, unsigned int getMax);
private:
ByteQueueNode *head, *tail;
};
enum ASNTag {INTEGER=0x02, BIT_STRING=0x03, SEQUENCE=0x10};
enum ASNIdFlag {CONSTRUCTED = 0x20};
unsigned int DERLengthEncode(unsigned int length, byte *output);
unsigned int DERLengthEncode(unsigned int length, BufferedTransformation &);
class BERDecodeErr {};
boolean BERLengthDecode(BufferedTransformation &, unsigned int &);
class BERSequenceDecoder : public BufferedTransformation
{
public:
BERSequenceDecoder(BufferedTransformation &inQueue);
~BERSequenceDecoder();
void Put(byte inByte) {}
void Put(const byte *, unsigned int) {}
unsigned long MaxRetrieveable()
{return inQueue.MaxRetrieveable();}
int Get(byte &outByte)
{return inQueue.Get(outByte);}
unsigned int Get(byte *outString, unsigned int getMax)
{return inQueue.Get(outString, getMax);}
private:
BufferedTransformation &inQueue;
boolean definiteLength;
unsigned int length;
};
class DERSequenceEncoder : public ByteQueue
{
public:
DERSequenceEncoder(BufferedTransformation &outQueue);
~DERSequenceEncoder();
private:
BufferedTransformation &outQueue;
};
extern "C" {
}
extern "C" {
extern void *memmove(void *, const void *, size_t);
extern char *strcpy(char *, const char *);
extern char *strncpy(char *, const char *, size_t);
extern char *strcat(char *, const char *);
extern char *strncat(char *, const char *, size_t);
extern int strcmp(const char *, const char *);
extern int strcoll(const char *, const char *);
extern int strncmp(const char *, const char *, size_t);
extern size_t strxfrm(char *, const char *, size_t);
extern void * __hide_memchr (const void *, int, size_t);
extern char * __hide_strchr (const char *, int);
extern size_t strcspn(const char *, const char *);
extern char * __hide_strpbrk (const char *, const char *);
extern char * __hide_strrchr (const char *, int);
extern size_t strspn(const char *, const char *);
extern char * __hide_strstr (const char *, const char *);
extern char *strtok(char *, const char *);
extern void *memset(void *, int, size_t);
extern char *strerror(int);
extern void *memccpy(void *, const void *, int, size_t);
extern char *strdup(const char *);
extern char *strsignal(int);
extern int ffs(const int);
extern int strcasecmp(const char *, const char *);
extern int strncasecmp(const char *, const char *, size_t);
}
typedef int ptrdiff_t;
extern "C" const char *strchr (const char *, int);
inline char *
strchr (char *s, int c)
{
return (char*) strchr ((const char *) s, c);
}
extern "C" const char *strpbrk (const char *, const char *);
inline char *
strpbrk (char *s1, const char *s2)
{
return (char *) strpbrk ((const char *) s1, s2);
}
extern "C" const char *strrchr (const char *, int);
inline char *
strrchr (char *s, int c)
{
return (char *) strrchr ((const char *) s, c);
}
extern "C" const char *strstr (const char *, const char *);
inline char *
strstr (char *s1, const char *s2)
{
return (char *) strstr ((const char *) s1, s2);
}
extern "C" void *memchr (const void *, int, size_t);
inline void *
memchr (void *s, int c, size_t n)
{
return (void *) memchr ((const void *) s, c, n);
}
typedef word16 unit;
typedef short signedunit;
typedef unit *unitptr;
extern short global_precision;
boolean mp_addc
(register unitptr r1,const unit * r2,register boolean carry);
boolean mp_subb
(register unitptr r1,const unit * r2,register boolean borrow);
boolean mp_rotate_left(register unitptr r1,register boolean carry);
void mp_shift_right_bits(register unitptr r1,register short bits);
short mp_compare(const unit * r1,const unit * r2);
boolean mp_inc(register unitptr r);
boolean mp_dec(register unitptr r);
void mp_neg(register unitptr r);
void mp_init(register unitptr r, word16 value);
short significance(const unit * r);
int mp_udiv(register unitptr remainder,register unitptr quotient,
const unit * dividend,const unit * divisor);
int mp_recip(register unitptr quotient,const unit * divisor);
int mp_div(register unitptr remainder,register unitptr quotient,
unit * dividend, unit * divisor);
word16 mp_shortdiv(register unitptr quotient,
const unit * dividend,register word16 divisor);
int mp_mod(register unitptr remainder,
const unit * dividend,const unit * divisor);
word16 mp_shortmod(register unitptr dividend,register word16 divisor);
int mp_mult(register unitptr prod,
const unit * multiplicand,const unit * multiplier);
int countbits(const unit * r);
int stage_peasant_modulus(const unit * n);
int stage_merritt_modulus(const unit * n);
int stage_upton_modulus(const unit * n);
int stage_smith_modulus(const unit * n);
int peasant_modmult(register unitptr prod,
const unit * multiplicand,const unit * multiplier);
int merritt_modmult(register unitptr prod,
const unit * multiplicand,const unit * multiplier);
int upton_modmult(register unitptr prod,
const unit * multiplicand,const unit * multiplier);
int smith_modmult(register unitptr prod,
const unit * multiplicand,const unit * multiplier);
void peasant_burn();
void merritt_burn();
void upton_burn();
void smith_burn();
int mp_modexp(register unitptr expout,const unit * expin,
const unit * exponent,const unit * modulus);
int mp_modexp_crt(unitptr expout, const unit * expin,
const unit * p, const unit * q, const unit * ep, const unit * eq, const unit * u);
word16 fetch_word16(byte *buf);
byte *put_word16(word16 w, byte *buf);
word32 fetch_word32(byte *buf);
byte *put_word32(word32 w, byte *buf);
int string_length(const char *s);
int str2reg(unit * reg,const char* digitstr);
int reg2str(char * s,const unit * n,short radix);
void mp_display(char * s,unitptr r);
word16 checksum(register byte * buf, register word16 count);
void cbc_xor(register unitptr dst, register unitptr src, word16 bytecount);
void hiloswap(byte * r1,short numbytes);
short mpi2reg(register unitptr r, register byte * buf);
short reg2mpi(register byte * buf, register unitptr r);
enum RandomNumberType {ANY, ODD, PRIME, BLUMINT};
class MPIRegister : public SecBlock<unit>
{
public:
MPIRegister() : SecBlock<unit>((2048 / 16 ) ) {}
};
class ostream;
class bignum
{
public:
bignum()
{}
bignum(unsigned long value);
bignum(const char *str)
{str2reg(reg, str);}
enum Signedness{UNSIGNED, SIGNED};
bignum(const byte *encodedBignum, unsigned int byteCount, Signedness s=UNSIGNED)
{Decode(encodedBignum, byteCount, s);}
bignum(const byte *BEREncodedInteger)
{BERDecode(BEREncodedInteger);}
bignum(BufferedTransformation &bt)
{BERDecode(bt);}
bignum(RandomNumberGenerator &rng, unsigned int bitcount)
{Randomize(rng, bitcount);}
bignum(RandomNumberGenerator &rng, const bignum &min, const bignum &max, RandomNumberType rnType=ANY)
{Randomize(rng, min, max, rnType);}
bignum(const bignum& t)
{memcpy(reg, t.reg, (2048 /8) );}
unsigned int Encode(byte *output) const;
unsigned int Encode(byte *output, unsigned int outputLen) const;
void Decode(const byte *input, unsigned int inputLen, Signedness=UNSIGNED);
unsigned int DEREncode(byte *output) const;
unsigned int DEREncode(BufferedTransformation &bt) const;
void BERDecode(const byte *input);
void BERDecode(BufferedTransformation &bt);
void Randomize(RandomNumberGenerator &rng, unsigned int bitcount);
void Randomize(RandomNumberGenerator &rng, const bignum &min, const bignum &max);
void Randomize(RandomNumberGenerator &rng, const bignum &min, const bignum &max, RandomNumberType rnType);
unsigned int ByteCount() const
{
return ((countbits( reg )+7)>>3) ;
}
int BitCount() const
{
return countbits(reg);
}
bignum& operator++()
{
mp_inc(reg);
return *this;
}
bignum& operator--()
{
mp_dec(reg);
return *this;
}
int operator!() const
{
return ( ((* (( reg.ptr )+( global_precision )-1) ) ==( 0 )) && (significance( reg.ptr )<=1) ) ;
}
bignum& operator=(const bignum& t)
{
memcpy(reg, t.reg, (2048 /8) );
return *this;
}
bignum& operator+=(const bignum& t)
{
mp_addc( reg , t.reg ,(boolean)0) ;
return *this;
}
bignum& operator-=(const bignum& t)
{
mp_subb( reg , t.reg ,(boolean)0) ;
return *this;
}
bignum& operator*=(const bignum& t)
{
*this = (*this) * t;
return *this;
}
bignum& operator/=(const bignum& t)
{
*this = (*this) / t;
return *this;
}
bignum& operator%=(const bignum& t)
{
*this = (*this) % t;
return *this;
}
bignum& operator<<=(unsigned int);
bignum& operator>>=(unsigned int);
unsigned MaxBitPrecision() const {return 2048 ;}
int operator[](unsigned int n) const;
friend bignum operator+(bignum a, const bignum &b)
{
return (a+=b);
}
friend bignum operator-(bignum a, const bignum &b)
{
return (a-=b);
}
friend bignum operator*(const bignum &a, const bignum &b);
friend bignum operator/(const bignum &a, const bignum &b);
friend bignum operator%(const bignum &a, const bignum &b);
friend bignum operator/(const bignum &a, word16 b);
friend word16 operator%(const bignum &a, word16 b);
friend bignum operator>>(bignum a, unsigned int n)
{return (a>>=n);}
friend bignum operator<<(bignum a, unsigned int n)
{return (a<<=n);}
void Negate() {mp_neg(reg);}
friend bignum operator-(bignum a)
{
a.Negate();
return a;
}
friend int operator==(const bignum &a, const bignum &b)
{
return (memcmp(a.reg.ptr, b.reg.ptr, (2048 /8) )==0);
}
friend int operator!=(const bignum& a, const bignum& b)
{
return (memcmp(a.reg.ptr, b.reg.ptr, (2048 /8) )!=0);
}
friend int operator>(const bignum& a, const bignum& b)
{
return (mp_compare(a.reg, b.reg)>0);
}
friend int operator>=(const bignum& a, const bignum& b)
{
return (mp_compare(a.reg, b.reg)>=0);
}
friend int operator<(const bignum& a, const bignum& b)
{
return (mp_compare(a.reg, b.reg)<0);
}
friend int operator<=(const bignum& a, const bignum& b)
{
return (mp_compare(a.reg, b.reg)<=0);
}
friend bignum a_times_b_mod_c(const bignum &x, const bignum& y, const bignum& m);
friend bignum a_exp_b_mod_c(const bignum &x, const bignum& e, const bignum& m);
class DivideErr {};
friend void Divide(bignum &r, bignum &q,
const bignum &a, const bignum &d,
Signedness s=SIGNED);
friend boolean Negative(const bignum &a)
{
return ((signedunit) (* ( a.reg.ptr ) ) < 0) ;
}
friend bignum Abs(bignum a)
{
(((signedunit) (* ( a.reg.ptr ) ) < 0) ? (mp_neg( a.reg.ptr ),TRUE) : FALSE) ;
return a;
}
friend ostream& operator<<(ostream& out, const bignum &a);
unit lsUnit() {return (* (( reg.ptr )+( global_precision )-1) ) ;}
private:
MPIRegister reg;
};
class RSAPublicKey : public PK_Encryptor, public PK_Decryptor,
public PK_Verifier
{
public:
RSAPublicKey(const bignum &n, const bignum &e);
RSAPublicKey(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText);
unsigned int Decrypt(const byte *cipherText, byte *plainText);
boolean Verify(const byte *message, unsigned int messageLen, const byte *signature);
unsigned int MaxPlainTextLength() const {return modulusLen-11;}
unsigned int CipherTextLength() const {return modulusLen;}
unsigned int MaxMessageLength() const {return modulusLen-11;}
unsigned int SignatureLength() const {return modulusLen;}
const bignum& Exponent() const {return e;}
const bignum& Modulus() const {return n;}
protected:
void RawEncrypt(const bignum &in, bignum &out) const;
private:
friend class RSAPrivateKey;
RSAPublicKey() {}
bignum n;
bignum e;
unsigned int modulusLen;
};
class RSAPrivateKey : public RSAPublicKey, public PK_Signer
{
public:
RSAPrivateKey(const bignum &n, const bignum &e, const bignum &d,
const bignum &p, const bignum &q, const bignum &dp, const bignum &dq, const bignum &u);
RSAPrivateKey(RandomNumberGenerator &rng, int keybits, bignum eStart=17);
RSAPrivateKey(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
void Encrypt(const byte *plainText, unsigned int plainTextLength, byte *cipherText);
unsigned int Decrypt(const byte *cipherText, byte *plainText);
void Encrypt(RandomNumberGenerator &, const byte *plainText, unsigned int plainTextLength, byte *cipherText)
{Encrypt(plainText, plainTextLength, cipherText);}
void Sign(const byte *message, unsigned int messageLen, byte *signature)
{Encrypt(message, messageLen, signature);}
void Sign(RandomNumberGenerator &, const byte *message, unsigned int messageLen, byte *signature)
{Encrypt(message, messageLen, signature);}
unsigned int MaxMessageLength() const {return modulusLen-11;}
unsigned int SignatureLength() const {return modulusLen;}
protected:
void RawEncrypt(const bignum &in, bignum &out) const;
private:
bignum d;
bignum p;
bignum q;
bignum dp;
bignum dq;
bignum u;
};
bignum Gcd(const bignum &a, const bignum &b);
bignum Inverse(const bignum &a, const bignum &m);
boolean IsSmallPrime(const bignum &p);
boolean SmallDivisorsTest(const bignum &p);
boolean FermatTest(const bignum &p, unsigned int rounds);
boolean RabinMillerTest(RandomNumberGenerator &rng, const bignum &w, unsigned int rounds);
inline boolean IsPrime(const bignum &p)
{
return (IsSmallPrime(p) || (SmallDivisorsTest(p) && FermatTest(p, 2)));
}
boolean NextPrime(bignum &p, const bignum &max, boolean blumInt=FALSE);
bignum a_exp_b_mod_pq(const bignum &a, const bignum &ep, const bignum &eq,
const bignum &p, const bignum &q, const bignum &u);
class PrimeAndGenerator
{
public:
PrimeAndGenerator(RandomNumberGenerator &rng, unsigned int pbits);
PrimeAndGenerator(RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits);
const bignum& Prime() const {return p;}
const bignum& SubPrime() const {return q;}
const bignum& Generator() const {return g;}
private:
bignum p, q, g;
};
extern "C" {
extern void __eprintf (const char *, const char *, unsigned, const char *);
}
RSAPublicKey::RSAPublicKey(const bignum &n, const bignum &e)
: n(n), e(e), modulusLen(n.ByteCount())
{
}
RSAPublicKey::RSAPublicKey(BufferedTransformation &bt)
{
BERSequenceDecoder seq(bt);
n.BERDecode(seq);
modulusLen = n.ByteCount();
e.BERDecode(seq);
}
void RSAPublicKey::DEREncode(BufferedTransformation &bt) const
{
DERSequenceEncoder seq(bt);
n.DEREncode(seq);
e.DEREncode(seq);
}
void RSAPublicKey::Encrypt(RandomNumberGenerator &rng, const byte *input, unsigned int inputLen, byte *output)
{unsigned int i;
((void) (( inputLen <= MaxPlainTextLength() ) ? 0 : (__eprintf ("%s:%u: failed assertion `%s'\n", "rsa.cpp" , 30 , "inputLen <= MaxPlainTextLength()" ), 0) )) ;
SecByteBlock pkcsBlock(modulusLen);
pkcsBlock[0] = 0;
pkcsBlock[1] = 2;
for (i = 2; i < modulusLen - inputLen - 1; i++)
{
do
pkcsBlock[i] = rng.GetByte();
while (pkcsBlock[i] == 0);
}
pkcsBlock[i++] = 0;
memcpy(pkcsBlock+i, input, inputLen);
bignum c;
RawEncrypt(bignum(pkcsBlock, modulusLen), c);
c.Encode(output, modulusLen);
}
unsigned int RSAPublicKey::Decrypt(const byte *input, byte *output)
{unsigned int i;
bignum m;
RawEncrypt(bignum(input, modulusLen), m);
SecByteBlock pkcsBlock(modulusLen);
m.Encode(pkcsBlock, modulusLen);
if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1))
return 0;
for (i = 2; i < modulusLen-1; i++)
if (pkcsBlock[i] != 0xff)
break;
if (pkcsBlock[i++] != 0)
return 0;
unsigned int outputLen = modulusLen - i;
if (outputLen > MaxPlainTextLength())
return 0;
memcpy (output, pkcsBlock+i, outputLen);
return outputLen;
}
boolean RSAPublicKey::Verify(const byte *message, unsigned int messageLen, const byte *signature)
{
((void) (( messageLen <= MaxMessageLength() ) ? 0 : (__eprintf ("%s:%u: failed assertion `%s'\n", "rsa.cpp" , 83 , "messageLen <= MaxMessageLength()" ), 0) )) ;
SecByteBlock m(MaxMessageLength());
unsigned int mLen = RSAPublicKey::Decrypt(signature, m);
return (mLen==messageLen && memcmp(message, m, mLen)==0);
}
void RSAPublicKey::RawEncrypt(const bignum &in, bignum &out) const
{
out = a_exp_b_mod_c(in, e, n);
}
RSAPrivateKey::RSAPrivateKey(const bignum &nIn, const bignum &eIn, const bignum &dIn,
const bignum &pIn, const bignum &qIn,
const bignum &dpIn, const bignum &dqIn, const bignum &uIn)
: RSAPublicKey(nIn, eIn)
{
d=dIn;
if (pIn < qIn)
{
p=pIn;
q=qIn;
dp=dpIn;
dq=dqIn;
}
else
{
p=qIn;
q=pIn;
dp=dqIn;
dq=dpIn;
}
u=uIn;
}
RSAPrivateKey::RSAPrivateKey(RandomNumberGenerator &rng, int keybits, bignum eStart)
{
p = bignum(rng, keybits/2, PRIME);
const bignum minQ = ((bignum(1) << (keybits-1)) / p) + 1;
const bignum maxQ = (bignum(1) << keybits) / p;
do
{
bignum temp(rng, minQ, maxQ, PRIME);
if (p>temp && p.BitCount()-(p-temp).BitCount() < 7)
{
q=p;
p=temp;
break;
}
if (p<temp && temp.BitCount()-(temp-p).BitCount() < 7)
{
q=temp;
break;
}
} while (1);
bignum phi = (p-1)*(q-1);
for (e = eStart; Gcd(e, phi)!=1; ++e, ++e);
d = Inverse(e, phi/Gcd(p-1, q-1));
dp = d % (p-1);
dq = d % (q-1);
u = Inverse(p, q);
n = p * q;
modulusLen = n.ByteCount();
}
RSAPrivateKey::RSAPrivateKey(BufferedTransformation &bt)
{
BERSequenceDecoder seq(bt);
bignum version(seq);
if (!!version)
throw BERDecodeErr() ;
n.BERDecode(seq);
modulusLen = n.ByteCount();
e.BERDecode(seq);
d.BERDecode(seq);
p.BERDecode(seq);
q.BERDecode(seq);
dp.BERDecode(seq);
dq.BERDecode(seq);
u.BERDecode(seq);
if (p>q)
{
swap(p, q);
swap(dp, dq);
}
}
void RSAPrivateKey::DEREncode(BufferedTransformation &bt) const
{
DERSequenceEncoder seq(bt);
byte version[] = {INTEGER, 1, 0};
seq.Put(version, sizeof(version));
n.DEREncode(seq);
e.DEREncode(seq);
d.DEREncode(seq);
q.DEREncode(seq);
p.DEREncode(seq);
dq.DEREncode(seq);
dp.DEREncode(seq);
u.DEREncode(seq);
}
|