Crypt-RSA-Yandex

 view release on metacpan or  search on metacpan

CP_RSA.cpp  view on Meta::CPAN

monty::monty( const vlong &M )
{
	m = M;
	N = 0; R = 1; while ( R < M ) { R += R; N += 1; }
	R1 = modinv( R-m, m );
	n1 = R - modinv( m, R );
}

void monty::mul( vlong &x, const vlong &y )
{
	// T = x*y;
	T.value->fast_mul( *x.value, *y.value, N*2 );

	// k = ( T * n1 ) % R;
	k.value->fast_mul( *T.value, *n1.value, N );

	// x = ( T + k*m ) / R;
	x.value->fast_mul( *k.value, *m.value, N*2 );
	x += T;
	x.value->shr( N );

	if (x>=m) x -= m;
}

vlong monty::exp( const vlong &x, const vlong &e )
{
	vlong result = R-m, t = ( x * R ) % m;
	unsigned bits = e.value->bits();
	unsigned i = 0;
	while (1)
	{
		if ( e.value->test(i) )
		{
			mul( result, t);
		}
		i += 1;
		if ( i == bits ) break;
		mul( t, t );
	}
	return ( result * R1 ) % m;
}

static vlong modexp( const vlong & x, const vlong & e, const vlong & m )
{
	monty me(m);
	return me.exp( x,e );
}

// RSA.CPP -----------------------------------

vlong public_key::encrypt( const vlong& plain )
{
#if defined(__DEBUG__)
	if ( plain >= m ) {
		printf("ERROR: plain too big for this key\n");
	}
#endif
	return modexp( plain, e, m );
}

vlong private_key::decrypt( const vlong& cipher )
{
	// Calculate values for performing decryption
	// These could be cached, but the calculation is quite fast
	vlong d = modinv( e, (p-(vlong)1)*(q-(vlong)1) );
	vlong u = modinv( p, q );
	vlong dp = d % (p-(vlong)1);
	vlong dq = d % (q-(vlong)1);

	// Apply chinese remainder theorem
	vlong a = modexp( cipher % p, dp, p );
	vlong b = modexp( cipher % q, dq, q );
	if ( b < a ) b += q;
	return a + p * ( ((b-a)*u) % q );
}

void vlong_pair_2_str (char *me_str,vlong &m,vlong &e)
{
	const char *hex_str = "0123456789ABCDEF";

	char tmp_str[MAX_CRYPT_BITS/2+1];

	unsigned int x;
	unsigned int me_len = 0;
	unsigned int i;
	unsigned int j;
	vlong m1 = m;
	vlong e1 = e;
	vlong zero = 0;

	i = 0;
	while (m1 != zero)
	{
		x = m1 % (vlong) 16;
		m1 = m1 / (vlong) 16;
		tmp_str[i++] = hex_str[x];
	}

	for (j=0; j < i; j++)
		me_str[me_len++] = tmp_str[i-1-j];

	me_str[me_len++] = '#';

	i = 0;
	while (e1 != zero)
	{
		x = e1 %(vlong)16;
		e1 = e1 / (vlong)16;
		tmp_str[i++] = hex_str[x];
	}

	for (j=0; j < i; j++)
		me_str[me_len++] = tmp_str[i-1-j];

	me_str[me_len] = 0;
}
void str_2_vlong_pair (const char *me_str,vlong &m,vlong &e)
{
	int i;
	int dash_pos = -1;
	m = 0;
	e = 0;

	int me_len = (int)strlen (me_str);

	for (i = me_len-1; i>=0; i--)
		if (me_str[i] == '#')
		{
			dash_pos = i;
			break;
		}

	if (dash_pos == 0)
		throw "Bad key: dash (`#') found at bad position";
	if (dash_pos == 1)
		throw "Bad key: no dash (`#') found ";


	for (i = 0; i<dash_pos; i++)
	{
		m = m * (vlong)16;
		if (me_str[i] > '9')
			m = m + (vlong) (me_str[i]-'A'+10);
		else
			m = m + (vlong) (me_str[i]-'0');
	}
	if (m == vlong(0))
		throw "Bad key: bad value before `#'";

	for (i = dash_pos+1; i<me_len; i++)
	{
		e = e * (vlong)16;
		if (me_str[i] > '9')
			e = e + (vlong) (me_str[i]-'A'+10);
		else
			e = e + (vlong) (me_str[i]-'0');
	}

	if (e == vlong(0))
		throw "Bad key: no value after `#'";

}



void private_key::MakeMeStr(char * me_str)
{
	vlong_pair_2_str (me_str,m,e);
}

void private_key::MakePqStr(char * me_str)
{
	vlong_pair_2_str (me_str,p,q);
}

void private_key::MakePq (const char *me_str)
{
	str_2_vlong_pair (me_str,p,q);
	{
	m = p*q;
	e = 50001; // must be odd since p-1 and q-1 are even
	while ( gcd(p-(vlong)1,e) != (vlong)1 || gcd(q-(vlong)1,e) != (vlong)1 ) e += 2;
	}

}


void public_key::MakeMe(const char *me_str)
{
	str_2_vlong_pair (me_str,m,e);
}

CCryptoProviderRSA::CCryptoProviderRSA()
{
}

CCryptoProviderRSA::~CCryptoProviderRSA()
{
}

void inline _rmemcpy (char *dst,const char *src,size_t size)
{
	src += size;
	while (size--)
		*dst++ = *(--src);
}

void CCryptoProviderRSA::GetBlockSize(int &enbs, int &debs)
{
	enbs=0;
	debs=0;
}

void CCryptoProviderRSA::EncryptPortion(const char *pt, size_t pt_size, char *ct, size_t &ct_size)
{
	vlong plain, cipher;

	const size_t bytes_per_unit = BPU / 8;

	size_t padding = (pt_size & 3) ? (4 - (pt_size & 3)) : 0;
	char tmp[MAX_CRYPT_BITS/4];

	// ensure big-endianness
	_rmemcpy(tmp, pt, pt_size);
	memset(tmp + pt_size, 0, padding);
	plain.load((unsigned int*)tmp, (int)(pt_size+padding) / bytes_per_unit);

	cipher = prkface.encrypt(plain);
	ct_size = cipher.get_nunits() * bytes_per_unit;

	// ensure big-endianness
	cipher.store((unsigned int*)tmp, (int)ct_size / bytes_per_unit);
	_rmemcpy(ct, tmp, ct_size);
}

void CCryptoProviderRSA::DecryptPortion(const char *ct, size_t ct_size, char *pt, size_t &pt_size)

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 0.654 second using v1.00-cache-2.02-grep-82fe00e-cpan-2cc899e4a130 )