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

📄 arith.c

📁 数据加密技术之几种算法 sa-faq-1
💻 C
字号:
/********************************************************************************									       **	Copyright (c) Martin Nicolay,  22. Nov. 1988			       **									       **	Wenn diese (oder sinngemaess uebersetzte) Copyright-Angabe enthalten   **	bleibt, darf diese Source fuer jeden nichtkomerziellen Zweck weiter    **	verwendet werden.						       **									       **	martin@trillian.megalon.de					       **									       ********************************************************************************/#include	"arith.h"/* *	!!!!!!!!!!!!!!!!!!!!!!!!!!!! ACHTUNG !!!!!!!!!!!!!!!!!!!!!!!!!!!! *	Es findet keinerlei Ueberpruefung auf Bereichsueberschreitung *	statt. Alle Werte muessen natuerliche Zahlen aus dem Bereich *		0 ... (MAXINT+1)^MAXLEN-1 sein. *	 *	 *	Bei keiner Funktion oder Hilsfunktion werden Annahmen getroffen, *	ueber die Verschiedenheit von Eingabe- & Ausgabe-Werten. * * *		Funktionen: * *	a_add( s1, s2, d ) *		NUMBER *s1,*s2,*d; *			*d = *s1 + *s2; * *	a_assign( *d, *s ) *		NUMBER *d,*s; *			*d = *s; * * int	a_cmp( c1, c2 ) *		NUMBER *c1,*c2; *			 1 :	falls *c1 >  *c2 *			 0 :	falls *c1 == *c2 *			-1 :	falls *c1 <  *c2 * *	a_div( d1, d2, q, r ) *		NUMBER *d1,*d2,*q,*r; *			*q = *d1 / *d2 Rest *r; * *	a_div2( n ) *		NUMBER *n; *			*n /= 2; * *	a_ggt( a, b, f ) *		NUMBER *a,*b,*f; *			*f = ( *a, *b ); * *	a_imult( n, m, d ) *		NUMBER *n; *		INT m; *		NUMBER *d; *			*d = *n * m * *	a_mult( m1, m2, d ) *		NUMBER *m1,*m2,*d; *			*d = *m1 * *m2; * *	a_sub( s1, s2, d ) *		NUMBER *s1,*s2,*d; *			*d = *s1 - *s2; * *		Modulare Funktionen *	m_init( n, o ) *		NUMBER *n,*o; *			Initialsierung der Modularen Funktionen *			o != 0 : *o = alter Wert * *	m_add( s1, s2, d ) *		NUMBER *s1, *s2, *d; *			*d = *s1 + *s2; * *	m_mult( m1, m2, d ) *		NUMBER *m1,*m2,*d; * *	m_exp( x, n, z ) *		NUMBER *x,*n,*z; *			*z = *x exp *n; * * *		Hilfs-Funktionen: * * int	n_bits( n, b ) *		NUMBER *n; *		int b; *			return( unterste b Bits der Dualdarstellung von n) * *	n_div( d1, z2, q, r ) *		NUMBER *d1,z2[MAXBIT],*q,*r; *			*q = *d1 / z2[0] Rest *r; *			z2[i] = z2[0] * 2^i,  i=0..MAXBIT-1 * * int	n_cmp( i1, i2, l ) *		INT i1[l], i2[l]; *			 1 :	falls i1 >  i2 *			 0 :	falls i1 == i2 *			-1 :	falls i1 <  i2 * * int	n_mult( n, m, d, l) *		INT n[l], m, d[]; *			d = m * n; *			return( sizeof(d) ); d.h. 'l' oder 'l+1' * * int	n_sub( p1, p2, p3, l, lo ) *		INT p1[l], p2[lo], p3[]; *			p3 = p1 - p2; *			return( sizeof(p3) ); d.h. '<= min(l,lo)' * * int	n_bitlen( n ) * 		NUMBER *n; *			return( sizeof(n) in bits ) * *//* * Konstante 1, 2 */NUMBER a_one = {	1,	{ (INT)1, },};NUMBER a_two = {#if MAXINT == 1	2,	{ 0, (INT)1, },#else	1,	{ (INT)2, },#endif};/* * Vergleiche zwei INT arrays der Laenge l */int n_cmp( i1, i2, l )INT *i1,*i2;{	i1 += (l-1);			/* Pointer ans Ende		*/ 	i2 += (l-1);	 	for (;l--;)		if ( *i1-- != *i2-- )			return( i1[1] > i2[1] ? 1 : -1 );		return(0);}/* * Vergleiche zwei NUMBER */int a_cmp( c1, c2 )NUMBER *c1,*c2;{	int l;					/* bei verschiedener Laenge klar*/	if ( (l=c1->n_len) != c2->n_len)		return( l - c2->n_len);						/* vergleiche als arrays	*/	return( n_cmp( c1->n_part, c2->n_part, l) );}/* * Zuweisung einer NUMBER (d = s) */void a_assign( d, s )NUMBER *d,*s;{	int l;		if (s == d)			/* nichts zu kopieren		*/		return;		if (l=s->n_len)		memcpy( d->n_part, s->n_part, sizeof(INT)*l);		d->n_len = l;}/* * Addiere zwei NUMBER (d = s1 + s2) */void a_add( s1, s2, d )NUMBER *s1,*s2,*d;{	int l,lo,ld,same;	register LONG sum;	register INT *p1,*p2,*p3;	register INT b;					/* setze s1 auch die groessere Zahl	*/	l = s1->n_len;	if ( (l=s1->n_len) < s2->n_len ) {		NUMBER *tmp = s1;				s1 = s2;		s2 = tmp;				l = s1->n_len;	}	ld = l;	lo = s2->n_len;	p1 = s1->n_part;	p2 = s2->n_part;	p3 = d->n_part;	same = (s1 == d);	sum = 0;		while (l --) {		if (lo) {		/* es ist noch was von s2 da	*/			lo--;			b = *p2++;		}		else			b = 0;		/* ansonten 0 nehmen		*/				sum += (LONG)*p1++ + (LONG)b;		*p3++ = TOINT(sum);		if (sum > (LONG)MAXINT) {	/* carry merken		*/			sum = 1;		}		else			sum = 0;		if (!lo && same && !sum)	/* nichts mehr zu tuen	*/			break;	}		if (sum) {		/* letztes carry beruecksichtigen	*/		ld++;		*p3 = sum;	}		d->n_len = ld;			/* Laenge setzen		*/}/* * Subtrahiere zwei INT arrays. return( Laenge Ergebniss ) * l == Laenge p1 * lo== Laenge p3 */int n_sub( p1, p2, p3, l, lo )INT *p1,*p2,*p3;int l,lo;{	int ld,lc,same;	int over = 0;	register LONG dif;	LONG a,b;		same = (p1 == p3);			/* frueher Abbruch moeglich */		for (lc=1, ld=0; l--; lc++) {		a = (LONG)*p1++;		if (lo) {			/* ist noch was von p2 da ? */			lo--;			b = (LONG)*p2++;		}		else			b=0;			/* ansonten 0 nehmen	*/		if (over)			/* frueherer Overflow	*/			b++;		if ( b > a ) {			/* jetzt Overflow ?	*/			over = 1;			dif = (MAXINT +1) + a;		}		else {			over = 0;			dif = a;		}		dif -= b;		*p3++ = (INT)dif;				if (dif)			/* Teil != 0 : Laenge neu */			ld = lc;		if (!lo && same && !over) {	/* nichts mehr zu tuen	*/			if (l > 0)		/* Laenge korrigieren	*/				ld = lc + l;			break;		}	}	return( ld );}/* * Subtrahiere zwei NUMBER (d= s1 - s2) */void a_sub( s1, s2, d )NUMBER *s1,*s2,*d;{	d->n_len = n_sub( s1->n_part, s2->n_part, d->n_part			 ,s1->n_len, s2->n_len );}/* * Mulitipliziere INT array der Laenge l mit einer INT (d = n * m) * return neue Laenge */int n_mult( n, m, d, l)register INT *n;register INT m;INT *d;{	int i;	register LONG mul;		for (i=l,mul=0; i; i--) {		mul += (LONG)m * (LONG)*n++;		*d++ = TOINT(mul);		mul  = DIVMAX1( mul );	}		if (mul) {		/* carry  ? */		l++;		*d = mul;	}		return( l );}/* * Mulitipliziere eine NUMBER mit einer INT (d = n * m) */void a_imult( n, m, d )NUMBER *n;INT m;NUMBER *d;{	if (m == 0)		d->n_len=0;	else if (m == 1)		a_assign( d, n );	else		d->n_len = n_mult( n->n_part, m, d->n_part, n->n_len );}  /* * Multipliziere zwei NUMBER (d = m1 * m2)  */void a_mult( m1, m2, d )NUMBER *m1,*m2,*d;{	static INT id[ MAXLEN ];		/* Zwischenspeicher	*/	register INT *vp;			/* Pointer darin	*/	register LONG sum;			/* Summe fuer jede Stelle */	register LONG tp1;			/* Zwischenspeicher fuer m1 */	register INT *p2;	INT *p1;	int l1,l2,ld,lc,l,i,j;		l1 = m1->n_len;	l2 = m2->n_len;	l = l1 + l2;	if (l >= MAXLEN)		abort();	for (i=l, vp=id; i--;)		*vp++ = 0;				/* ohne Uebertrag in Zwischenspeicher multiplizieren */	for ( p1 = m1->n_part, i=0; i < l1 ; i++, p1++ ) {		tp1 = (LONG)*p1;				vp = &id[i];		sum = 0;		for ( p2 = m2->n_part, j = l2; j--;) {			sum += (LONG)*vp + (tp1 * (LONG)*p2++);			*vp++ = TOINT( sum );			sum = DIVMAX1(sum);		}		*vp++ += (INT)sum;	}			/* jetzt alle Uebertraege beruecksichtigen	*/	ld = 0;	for (lc=0, vp=id, p1=d->n_part; lc++ < l;) {		if ( *p1++ = *vp++ )			ld = lc;	}		d->n_len = ld;}/* * Dividiere Zwei NUMBER mit Rest (q= d1 / z2[0] Rest r) * z2[i] = z2[0] * 2^i,  i=0..MAXBIT-1 * r = 0 : kein Rest * q = 0 : kein Quotient */void n_div( d1, z2, q, r )NUMBER *d1,*z2,*q,*r;{	static	NUMBER dummy_rest;  /* Dummy Variable, falls r = 0 */	static	NUMBER dummy_quot;  /* Dummy Variable, falla q = 0 */	INT *i1,*i1e,*i3;	int l2,ld,l,lq;#if MAXINT != 1	INT z;	int pw,l2t;#endif	if (!z2->n_len)		abort();			if (!r)		r = &dummy_rest;	if (!q)		q = &dummy_quot;		a_assign( r, d1 );	/* Kopie von d1 in den Rest		*/		l2= z2->n_len;		/* Laenge von z2[0]			*/	l = r->n_len - l2;	/* Laenge des noch ''rechts'' liegenden					Stuecks von d1			*/	lq= l +1;		/* Laenge des Quotienten		*/	i3= q->n_part + l;	i1= r->n_part + l;	ld = l2;		/* aktuelle Laenge des ''Vergleichsstuecks''					von d1				*/	i1e= i1 + (ld-1);		for (; l >= 0; ld++, i1--, i1e--, l--, i3--) {		*i3 = 0;		if (ld == l2 && ! *i1e) {			ld--;			continue;		}				if ( ld > l2 || (ld == l2 && n_cmp( i1, z2->n_part, l2) >= 0 ) ) {#if MAXINT != 1				/* nach 2er-Potenzen zerlegen	*/			for (pw=MAXBIT-1, z=(INT)HIGHBIT; pw >= 0; pw--, z /= 2) {				if ( ld > (l2t= z2[pw].n_len)					|| (ld == l2t					    && n_cmp( i1, z2[pw].n_part, ld) >= 0) ) {					ld = n_sub( i1, z2[pw].n_part, i1, ld, l2t );					(*i3) += z;				}			}#else				/* bei MAXINT == 1 alles viel einfacher	*/			ld = n_sub( i1, z2->n_part, i1, ld, l2 );			(*i3) ++;#endif		}	}				/* Korrektur, falls l von Anfang an Negativ war */	l ++;	lq -= l;	ld += l;		if (lq>0 && !q->n_part[lq -1])	/* evtl. Laenge korrigieren	*/		lq--;		q->n_len = lq;	r->n_len = ld -1;}/* * Dividiere Zwei NUMBER mit Rest (q= d1 / z2[0] Rest r) * z2[i] = z2[0] * 2^i,  i=0..MAXBIT-1 * r = 0 : kein Rest * q = 0 : kein Quotient */void a_div( d1, d2, q, r )NUMBER *d1,*d2,*q,*r;{#if MAXINT != 1	NUMBER z2[MAXBIT];	INT z;	int i;		a_assign( &z2[0], d2 );	for (i=1,z=2; i < MAXBIT; i++, z *= 2)		a_imult( d2, z, &z2[i] );		d2 = z2;#endif	n_div( d1, d2, q, r );}/* * Dividiere eine NUMBER durch 2 */void a_div2( n )NUMBER *n;{#if MAXBIT == LOWBITS	register INT *p;	int i;#if MAXINT != 1	register INT h;	register int c;	c=0;	i= n->n_len;	p= &n->n_part[i-1];		for (; i--;) {		if (c) {			c = (h= *p) & 1;			h /= 2;			h |= HIGHBIT;		}		else {			c = (h= *p) & 1;			h /= 2;		}				*p-- = h;	}		if ( (i= n->n_len) && n->n_part[i-1] == 0 )		n->n_len = i-1;#else  /* MAXBIT != 1 */	p = n->n_part;	i = n->n_len;		if (i) {		n->n_len = i-1;		for (; --i ; p++)			p[0] = p[1];	}#endif /* MAXBIT != 1 */#else  /* MAXBIT == LOWBITS */	a_div( n, &a_two, n, NUM0P );#endif /* MAXBIT == LOWBITS */}/* *	MODULO-FUNKTIONEN */static NUMBER mod_z2[ MAXBIT ];/* * Init */void m_init( n, o )NUMBER *n,*o;{	INT z;	int i;		if (o)		a_assign( o, &mod_z2[0] );		if (! a_cmp( n, &mod_z2[0] ) )		return;		for (i=0,z=1; i < MAXBIT; i++, z *= 2)		a_imult( n, z, &mod_z2[i] );}void m_add( s1, s2, d )NUMBER *s1, *s2, *d;{	a_add( s1, s2, d );	if (a_cmp( d, mod_z2 ) >= 0)		a_sub( d, mod_z2, d );}void m_mult( m1, m2, d )NUMBER *m1,*m2,*d;{	a_mult( m1, m2, d );	n_div( d, mod_z2, NUM0P, d );}/* * Restklassen Exponent */void m_exp( x, n, z )NUMBER *x,*n,*z;{	NUMBER xt,nt;		a_assign( &nt, n );	a_assign( &xt, x );	a_assign( z, &a_one );		while (nt.n_len) {		while ( ! (nt.n_part[0] & 1) ) {			m_mult( &xt, &xt, &xt );			a_div2( &nt );		}		m_mult( &xt, z, z );		a_sub( &nt, &a_one, &nt );	}}/* * GGT */void a_ggt( a, b, f )NUMBER *a,*b,*f;{	NUMBER t[2];	int at,bt, tmp;		a_assign( &t[0], a ); at= 0;	a_assign( &t[1], b ); bt= 1;		if ( a_cmp( &t[at], &t[bt] ) < 0 ) {		tmp= at; at= bt; bt= tmp;	}				/* euklidischer Algorithmus		*/	while ( t[bt].n_len ) {		a_div( &t[at], &t[bt], NUM0P, &t[at] );		tmp= at; at= bt; bt= tmp;	}		a_assign( f, &t[at] );}	/* * die untersten b bits der Dualdarstellung von n * die bits muessen in ein int passen */int n_bits(n,b)NUMBER *n;{	INT *p;	int l;	unsigned r;	int m = (1<<b) -1;	if ( n->n_len == 0)		return(0);		if (LOWBITS >= b)		return( n->n_part[0] & m );#if LOWBITS != 0	l = (b-1) / LOWBITS;#else	l = n->n_len -1;#endif	for (p= &n->n_part[l],r=0; l-- >= 0 && b > 0; b-= LOWBITS, p--) {		r  = MULMAX1( r );		r += (unsigned)*p;	}	return( r & m );}/* * Anzahl der bits von n bei Dualdarstellung */int n_bitlen( n )NUMBER *n;{	NUMBER b;	int i;		a_assign( &b, &a_one );		for (i=0; a_cmp( &b, n ) <= 0; a_mult( &b, &a_two, &b ), i++)		;		return(i);}

⌨️ 快捷键说明

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