| // 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); |
| } |