⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpilib.cpp

📁 RSA算法的VC源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* C source code for multiprecision arithmetic library routines.


   These routines implement all of the multiprecision arithmetic
   necessary for number-theoretic cryptographic algorithms such as
   ElGamal, Diffie-Hellman, Rabin, or factoring studies for large
   composite numbers, as well as Rivest-Shamir-Adleman (RSA) public
   key cryptography.
 */

/* #define COUNTMULTS *//* count modmults for performance studies */
#include "stdafx.h"

#ifndef poll_for_break
#define poll_for_break()	/* stub */
#endif

#include "mpilib.h"

#ifdef mp_smula
#ifdef mp_smul
Error:Both mp_smula and mp_smul cannot be defined.
#else
#define mp_smul	mp_smula
#endif
#endif

/* set macros for MULTUNIT */
#ifdef MUNIT8
#define MULTUNITSIZE   8
typedef unsigned char MULTUNIT;
#ifdef UNIT8
#define MULTUNIT_SIZE_SAME
#endif
#else				/* not MUNIT8 */
#ifdef MUNIT32
#define MULTUNITSIZE   32
typedef unsigned long MULTUNIT;
#ifdef UNIT32
#define MULTUNIT_SIZE_SAME
#else
/* #error is not portable, this has the same effect */
#include "UNITSIZE cannot be smaller than MULTUNITSIZE"
#endif
#else				/* assume MUNIT16 */
#define MULTUNITSIZE   16
typedef unsigned short MULTUNIT;
#ifdef UNIT16
#define MULTUNIT_SIZE_SAME
#endif				/* UNIT16 */
#ifdef UNIT8
#include "UNITSIZE cannot be smaller than MULTUNITSIZE"
#endif				/* UNIT8 */
#endif				/* MUNIT32 */
#endif				/* MUNIT8 */

#define MULTUNIT_msb    ((MULTUNIT)1 << (MULTUNITSIZE-1))	/* msb of
								   MULTUNIT */
#define DMULTUNIT_msb   (1L << (2*MULTUNITSIZE-1))
#define MULTUNIT_mask   ((MULTUNIT)((1L << MULTUNITSIZE)-1))
#define MULTUNITs_perunit   (UNITSIZE/MULTUNITSIZE)


void mp_smul(MULTUNIT * prod, MULTUNIT * multiplicand, MULTUNIT multiplier);
void mp_dmul(unitptr prod, unitptr multiplicand, unitptr multiplier);

short global_precision = 0;	/* units of precision for all routines */
/*      global_precision is the unit precision last set by set_precision.
   Initially, set_precision() should be called to define global_precision
   before using any of these other multiprecision library routines.
   i.e.:   set_precision(MAX_UNIT_PRECISION);
 */

/*************** multiprecision library primitives ****************/
/*      The following portable C primitives should be recoded in assembly.
   The entry point name should be defined, in "mpilib.h" to the external
   entry point name.  If undefined, the C version will be used.
 */

typedef unsigned long int ulint;

UINT random(UINT nMax)//0-->nMax-1
{
	int nRand=rand();
	float fMap=(float)(nMax-1)/RAND_MAX;
	float fRetVal=(float)nRand*fMap+0.5F;
	return (UINT)fRetVal;
}

#ifndef mp_addc
/* 
   multiprecision add with carry r2 to r1, result in r1
   carry is incoming carry flag-- value should be 0 or 1
*/
boolean mp_addc
 (register unitptr r1, register unitptr r2, register boolean carry)
{
    register unit x;
    short precision;		/* number of units to add */
    precision = global_precision;
    make_lsbptr(r1, precision);
    make_lsbptr(r2, precision);
    while (precision--) {
	if (carry) {
	    x = *r1 + *r2 + 1;
	    carry = (*r2 >= (unit) (~*r1));
	} else {
	    x = *r1 + *r2;
	    carry = (x < *r1);
	}
	post_higherunit(r2);
	*post_higherunit(r1) = x;
    }
    return carry;		/* return the final carry flag bit */
}				/* mp_addc */
#endif				/* mp_addc */

#ifndef mp_subb

/* 
   multiprecision subtract with borrow, r2 from r1, result in r1
   borrow is incoming borrow flag-- value should be 0 or 1
 */
boolean mp_subb
 (register unitptr r1, register unitptr r2, register boolean borrow)
{
    register unit x;
    short precision;		/* number of units to subtract */
    precision = global_precision;
    make_lsbptr(r1, precision);
    make_lsbptr(r2, precision);
    while (precision--) {
	if (borrow) {
	    x = *r1 - *r2 - 1;
	    borrow = (*r1 <= *r2);
	} else {
	    x = *r1 - *r2;
	    borrow = (*r1 < *r2);
	}
	post_higherunit(r2);
	*post_higherunit(r1) = x;
    }
    return borrow;		/* return the final carry/borrow flag bit */
}				/* mp_subb */
#endif				/* mp_subb */

#ifndef mp_rotate_left

/*
   multiprecision rotate left 1 bit with carry, result in r1.
   carry is incoming carry flag-- value should be 0 or 1
*/
boolean mp_rotate_left(register unitptr r1, register boolean carry)
{
    register int precision;	/* number of units to rotate */
    unsigned int mcarry = carry, nextcarry;	/* int is supposed to be
						 * the efficient size for ops*/
    precision = global_precision;
    make_lsbptr(r1, precision);
    while (precision--) {
	nextcarry = (((signedunit) * r1) < 0);
	*r1 = (*r1 << 1) | mcarry;
	mcarry = nextcarry;
	pre_higherunit(r1);
    }
    return nextcarry;		/* return the final carry flag bit */
}				/* mp_rotate_left */
#endif				/* mp_rotate_left */

/************** end of primitives that should be in assembly *************/

/* The mp_shift_right_bits function is not called in any time-critical
   situations in public-key cryptographic functions, so it doesn't
   need to be coded in assembly language.
 */

/*
   multiprecision shift right bits, result in r1.
   bits is how many bits to shift, must be <= UNITSIZE.
*/
void mp_shift_right_bits(register unitptr r1, register short bits)
{
    register short precision;	/* number of units to shift */
    register unit carry, nextcarry, bitmask;
    register short unbits;
    if (bits == 0)
	return;			/* shift zero bits is a no-op */
    carry = 0;
    bitmask = power_of_2(bits) - 1;
    unbits = UNITSIZE - bits;	/* shift bits must be <= UNITSIZE */
    precision = global_precision;
    make_msbptr(r1, precision);
    if (bits == UNITSIZE) {
	while (precision--) {
	    nextcarry = *r1;
	    *r1 = carry;
	    carry = nextcarry;
	    pre_lowerunit(r1);
	}
    } else {
	while (precision--) {
	    nextcarry = *r1 & bitmask;
	    *r1 >>= bits;
	    *r1 |= carry << unbits;
	    carry = nextcarry;
	    pre_lowerunit(r1);
	}
    }
}				/* mp_shift_right_bits */

#ifndef mp_compare

/*
 * Compares multiprecision integers *r1, *r2, and returns:
 * -1 iff *r1 < *r2
 *  0 iff *r1 == *r2
 * +1 iff *r1 > *r2
 */
short mp_compare(register unitptr r1, register unitptr r2)
{
    register short precision;	/* number of units to compare */

    precision = global_precision;
    make_msbptr(r1, precision);
    make_msbptr(r2, precision);
    do {
	if (*r1 < *r2)
	    return -1;
	if (*post_lowerunit(r1) > *post_lowerunit(r2))
	    return 1;
    } while (--precision);
    return 0;			/*  *r1 == *r2  */
}				/* mp_compare */
#endif				/* mp_compare */

/* Increment multiprecision integer r. */
boolean mp_inc(register unitptr r)
{
    register short precision;
    precision = global_precision;
    make_lsbptr(r, precision);
    do {
	if (++(*r))
	    return 0;		/* no carry */
	post_higherunit(r);
    } while (--precision);
    return 1;			/* return carry set */
}				/* mp_inc */

/* Decrement multiprecision integer r. */
boolean mp_dec(register unitptr r)
{
    register short precision;
    precision = global_precision;
    make_lsbptr(r, precision);
    do {
	if ((signedunit) (--(*r)) != (signedunit) - 1)
	    return 0;		/* no borrow */
	post_higherunit(r);
    } while (--precision);
    return 1;			/* return borrow set */
}				/* mp_dec */

/* Compute 2's complement, the arithmetic negative, of r */
void mp_neg(register unitptr r)
{
    register short precision;	/* number of units to negate */
    precision = global_precision;
    mp_dec(r);			/* 2's complement is 1's complement plus 1 */
    do {			/* now do 1's complement */
	*r = ~(*r);
	r++;
    } while (--precision);
}				/* mp_neg */

#ifndef mp_move

void mp_move(register unitptr dst, register unitptr src)
{
    register short precision;	/* number of units to move */
    precision = global_precision;
    do {
	*dst++ = *src++;
    } while (--precision);
}				/* mp_move */
#endif				/* mp_move */

/* Init multiprecision register r with short value. */
void mp_init(register unitptr r, word16 value)
{	/* Note that mp_init doesn't extend sign bit for >32767 */

    unitfill0(r, global_precision);
    make_lsbptr(r, global_precision);
    *post_higherunit(r) = value;
#ifdef UNIT8
    *post_higherunit(r) = value >> UNITSIZE;
#endif
}				/* mp_init */

/* Returns number of significant units in r */
short significance(register unitptr r)
{
    register short precision;
    precision = global_precision;
    make_msbptr(r, precision);
    do {
	if (*post_lowerunit(r))
	    return precision;
    } while (--precision);
    return precision;
}				/* significance */


#ifndef unitfill0

/* Zero-fill the unit buffer r. */
void unitfill0(unitptr r, word16 unitcount)
{
    while (unitcount--)
	*r++ = 0;
}				/* unitfill0 */
#endif				/* unitfill0 */

/* Unsigned divide, treats both operands as positive. */
int mp_udiv(register unitptr remainder, register unitptr quotient,
	    register unitptr dividend, register unitptr divisor)
{
    int bits;
    short dprec;
    register unit bitmask;

    if (testeq(divisor, 0))
	return -1;		/* zero divisor means divide error */
    mp_init0(remainder);
    mp_init0(quotient);
    /* normalize and compute number of bits in dividend first */
    init_bitsniffer(dividend, bitmask, dprec, bits);
    /* rescale quotient to same precision (dprec) as dividend */
    rescale(quotient, global_precision, dprec);
    make_msbptr(quotient, dprec);

    while (bits--) {
	mp_rotate_left(remainder,
		       (boolean) (sniff_bit(dividend, bitmask) != 0));
	if (mp_compare(remainder, divisor) >= 0) {
	    mp_sub(remainder, divisor);
	    stuff_bit(quotient, bitmask);
	}
	bump_2bitsniffers(dividend, quotient, bitmask);
    }
    return 0;
}				/* mp_udiv */

#ifdef UPTON_OR_SMITH

#define RECIPMARGIN 0		/* extra margin bits used by mp_recip() */

/* Compute reciprocal (quotient) as 1/divisor.  Used by faster modmult. */
int mp_recip(register unitptr quotient, register unitptr divisor)
{
    int bits;
    short qprec;
    register unit bitmask;
    unit remainder[MAX_UNIT_PRECISION];
    if (testeq(divisor, 0))
	return -1;		/* zero divisor means divide error */
    mp_init0(remainder);
    mp_init0(quotient);

    /* normalize and compute number of bits in quotient first */
    bits = countbits(divisor) + RECIPMARGIN;
    bitmask = bitmsk(bits);	/* bitmask within a single unit */
    qprec = bits2units(bits + 1);
    mp_setbit(remainder, (bits - RECIPMARGIN) - 1);
    /* rescale quotient to precision of divisor + RECIPMARGIN bits */
    rescale(quotient, global_precision, qprec);
    make_msbptr(quotient, qprec);

    while (bits--) {
	mp_shift_left(remainder);
	if (mp_compare(remainder, divisor) >= 0) {
	    mp_sub(remainder, divisor);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -