//改变大数尺寸
void flex_unit::reserve( unsigned x )
{
if (x > z)
{
unsigned * na = new unsigned[x];
for (unsigned i=0;i<n;i+=1) na[i] = a[i];
delete [] a;
a = na;
z = x;
}
}
//根据索引设置元素值
void flex_unit::set( unsigned i, unsigned x )
{
if ( i < n )
{
a[i] = x;
if (x==0)
while (n && a[n-1]==0) //去除高位0
n-=1;
}
else if ( x )
{
reserve(i+1);
for (unsigned j=n;j<i;j+=1) a[j] = 0;
a[i] = x;
n = i+1;
}
}
//快速乘法
void flex_unit::fast_mul( flex_unit &x, flex_unit &y, unsigned keep )
{
// *this = (x*y) % (2**keep)
unsigned i,limit = (keep+BPU-1)/BPU; //运算结果单元数
reserve(limit);
for (i=0; i<limit; i+=1)
a[i] = 0;
unsigned min = x.n;
if (min>limit)
min = limit;
for (i=0; i<min; i+=1)
{
unsigned m = x.a[i];
unsigned c = 0;
unsigned min = i+y.n;
if (min>limit) min = limit;
for ( unsigned j=i; j<min; j+=1 )
{
//此处代码为运算关键,可使用机器或汇编代码以加快速度
// c:a[j] = a[j] + c + m*y.a[j-i];
unsigned w, v = a[j], p = y.a[j-i];
v += c; c = ( v < c );
w = lo(p)*lo(m); v += w; c += ( v < w );
w = lo(p)*hi(m); c += hi(w); w = lh(w); v += w; c += ( v < w );
w = hi(p)*lo(m); c += hi(w); w = lh(w); v += w; c += ( v < w );
c += hi(p) * hi(m);
a[j] = v;
}
while ( c && j<limit )
{
a[j] += c;
c = a[j] < c;
j += 1;
}
}
//去除不必要的bit
keep %= BPU;
if (keep)
a[limit-1] &= (1<<keep)-1;
//计算使用单元数
while (limit && a[limit-1]==0)
limit-=1;
n = limit;
};
// 测试大数是否为0
int vlong_value::is_zero() const
{
return n==0;
}
//测试第i位(bit)值是否为0
int vlong_value::test( unsigned i ) const
{
return ( get(i/BPU) & (1<<(i%BPU)) ) != 0;
}
//获取大数位(bit)数
unsigned vlong_value::bits() const
{
unsigned x = n*BPU;
while (x && test(x-1)==0) x -= 1;
return x;
}
//比较两个大数值大小
int vlong_value::cf( vlong_value& x ) const
{
if ( n > x.n ) return +1;
if ( n < x.n ) return -1;
unsigned i = n;
while (i)
{
i -= 1;
if ( get(i) > x.get(i) ) return +1;
if ( get(i) < x.get(i) ) return -1;
}
return 0;
}
//按位左移
void vlong_value::shl()
{
unsigned carry = 0;
unsigned N = n;
for (unsigned i=0;i<=N;i+=1)
{
unsigned u = get(i);
set(i,(u<<1)+carry);
carry = u>>(BPU-1);
}
}
//按位右移
void vlong_value::shr()
{
unsigned carry = 0;
unsigned i=n;
while (i)
{
i -= 1;
unsigned u = get(i);
set(i,(u>>1)+carry);
carry = u<<(BPU-1);
}
}
//左移x位
void vlong_value::shr( unsigned x )
{
unsigned delta = x/BPU;
x %= BPU;
for (unsigned i=0;i<n;i+=1)
{
unsigned u = get(i+delta);
if (x)
{
u >>= x;
u += get(i+delta+1) << (BPU-x);
}
set(i,u);
}
}
//大数加法
void vlong_value::add( vlong_value & x )
{
unsigned carry = 0;
unsigned max = n; if (max<x.n) max = x.n;
reserve(max);
for (unsigned i=0;i<max+1;i+=1)
{
unsigned u = get(i);
u = u + carry; carry = ( u < carry );
unsigned ux = x.get(i);
u = u + ux; carry += ( u < ux );
set(i,u);
}
}
//大数减法
void vlong_value::subtract( vlong_value & x )
{
unsigned carry = 0;
unsigned N = n;
for (unsigned i=0;i<N;i+=1)
{
unsigned ux = x.get(i);
ux += carry;
if ( ux >= carry )
{
unsigned u = get(i);
unsigned nu = u - ux;
carry = nu > u;
set(i,nu);
}
}
}
//使用无符号整数x初始化大数
void vlong_value::init( unsigned x )
{
clear();
set(0,x);
}
//将参数x(大数类型)值赋给本实例
void vlong_value::copy( vlong_value& x )
{
clear();
unsigned i=x.n;
while (i) { i -= 1; set( i, x.get(i) ); }
}
vlong_value::vlong_value()
{
share = 0;
}
//大数乘法
void vlong_value::mul( vlong_value& x, vlong_value& y )
{
fast_mul( x, y, x.bits()+y.bits() );
}
//大数除法
void vlong_value::divide( vlong_value& x, vlong_value& y, vlong_value& rem )
{
init(0);
rem.copy(x);
vlong_value m,s;
m.copy(y);
s.init(1);
while ( rem.cf(m) > 0 )
{
m.shl();
s.shl();
}
while ( rem.cf(y) >= 0 )
{
while ( rem.cf(m) < 0 )
{
m.shr();
s.shr();
}
rem.subtract( m );
add( s );
}
}
//辗转相除求最大因子
vlong gcd( const vlong &X, const vlong &Y )
{
vlong x=X, y=Y;
while (1)
{
if ( y == (vlong)0 ) return x;
x = x % y;
if ( x == (vlong)0 ) return y;
y = y % x;
}
}
//密钥产生流程最后一步,Euclid 算法
// 返回在1到m-1之间的长整数i,使i*a = 1 mod m
// a必须为在1到m-1之间的长整数
vlong modinv( const vlong &a, const vlong &m )
{
vlong j=1,i=0,b=m,c=a,x,y;
while ( c != (vlong)0 )
{
x = b / c;
y = b - x*c;
b = c;
c = y;
y = j;
j = i - j*x;
i = y;
}
if ( i < (vlong)0 )
i += m;
return i;
}
//monty:求模与幂的相关类,主要用于分块加密与解密
//加密: = ^e ( mod n )
//解密: = ^d ( mod n )
class monty
{
vlong R,R1,m,n1;
vlong T,k; //工作寄存器
unsigned N; //R的位(bit)数
void mul( vlong &x, const vlong &y );
public:
vlong exp( const vlong &x, const vlong &e );
monty( const vlong &M );
};
//赋M为默认除数,即加/解密式中的n
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 );
}
// 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;
}
//返回值= (x^e)%(this->m)
vlong monty::exp( const vlong &x, const vlong &e )
{
vlong result = R-m;
vlong 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;
}
//初始化质数表
unsigned SS = 8*NP; //粗略估计质数表上限
char * b = new char[SS+1];
for (unsigned i=0;i<=SS;i+=1)
b[i] = 1;
unsigned p = 2;
while (1)
{
// skip composites
while ( b
== 0 ) p += 1;
if ( p == SS ) break;
pl[np] = p;
np += 1;
if ( np == NP ) break;
// cross off multiples
unsigned c = p*2;
while ( c < SS )
{
b[c] = 0;
c += p;
}
p += 1;
}
delete [] b;
}
//寻找第一个>=start的质数
vlong prime_factory::find_prime( vlong & start )
{
unsigned SS = 1000; //1000通常已足够
char * b = new char[SS]; //后备质数检验位,若SS[i]=0,则不需要用
//费马小定理(is_probable_prime)检验start+i,因为它
//必非质数
unsigned tested = 0; //使用is_probable_prime函数检验过的后备质数次数
while (1)
{
unsigned i;
for (i=0;i<SS;i+=1)
b[i] = 1;
for (i=0;i<np;i+=1)
{
unsigned p = pl[i];
unsigned r = start % (vlong)p; //取模运算较慢,此处可专门设计函数做取模计算
if (r)
r = p - r;
// 去除所有能被p除尽的后备质数
while ( r < SS )
{
b[r] = 0;
r += p;
}
}
// 检验后备质数
for (i=0;i<SS;i+=1)
{
if ( b[i] )
{
tested += 1;
if ( is_probable_prime(start) )
return start;
}
start += 1;
}
}
delete [] b;
}
//由字符串r1和r2创建p、q和公钥
void private_key::create( const char * r1, const char * r2 )
{
// 由r1和r2产生质数p、q
{
prime_factory pf;
p = pf.find_prime( from_str(r1) );
q = pf.find_prime( from_str(r2) );
if ( p > q )
{
vlong tmp = p;
p = q;
q = tmp;
}
}
// 计算公钥
//从[0,(p-1)(q-1)-1]中随机选取加密密钥e,使得e和(p-1)(q-1)互质。此处
//为使e较大,直接从一较大数开始选取(50001)
{
m = p*q;
e = 50001; //必须为奇数,因p-1,q-1均为偶数
while ( gcd(p-(vlong)1,e) != (vlong)1 || gcd(q-(vlong)1,e) != (vlong)1 )
e += 2;
}
}
//加密明文
vlong public_key::encrypt( const vlong& plain )
{
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);
// 应用同余定理
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 );
}
//rsa类简单使用实例
#include "rsa.h"
#include <iostream>
using namespace std;
main()
{
private_key pkey;
pkey.create("abcdefgaaaaaaaaaaaaaaaaaa","deeeeeeeeeeeeeeeefffffffff");
vlong m;
m=from_str("abbbbccc");
pkey.encrypt(m);
void DES::deskey(unsigned char key[8], Mode md) /* Thanks to James Gillogly & Phil Karn! */
{
register int i, j, l, m, n;
unsigned char pc1m[56], pcr[56];
unsigned long kn[32];
for (j = 0; j < 56; j++) {
l = pc1[j];
m = l & 07;
pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1:0;
}
for (i = 0; i < 16; i++) {
if (md == DECRYPT) m = (15 - i) << 1;
else m = i << 1;
n = m + 1;
kn[m] = kn[n] = 0L;
for (j = 0; j < 28; j++) {
l = j + totrot[i];
if (l < 28) pcr[j] = pc1m[l];
else pcr[j] = pc1m[l - 28];
}
for (j = 28; j < 56; j++) {
l = j + totrot[i];
if (l < 56) pcr[j] = pc1m[l];
else pcr[j] = pc1m[l - 28];
}
for (j = 0; j < 24; j++) {
if (pcr[ pc2[j] ]) kn[m] |= bigbyte[j];
if (pcr[ pc2[j+24] ]) kn[n] |= bigbyte[j];
}
}
cookey(kn);
return;
}