Crypt-RSA-Yandex
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
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 distributionview release on metacpan - search on metacpan
( run in 0.654 second using v1.00-cache-2.02-grep-82fe00e-cpan-2cc899e4a130 )