parent
b7bc283c66
commit
da630e1253
|
@ -1,741 +0,0 @@
|
|||
// 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);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue