现在的位置: 首页 > 综合 > 正文

一份RSA的源码(C#)

2013年10月03日 ⁄ 综合 ⁄ 共 4433字 ⁄ 字号 评论关闭
 

Using directives 

namespace rsatest 


/* 
    RSA算法 
      1978年就出现了这种算法,它是第一个既能用于数据加密也能用于数字签名的算法。 
    它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, 
    AdiShamir 和Leonard Adleman。但RSA的安全性一直未能得到理论上的证明。 

      RSA的安全性依赖于大数难于分解这一特点。公钥和私钥都是两个大素数(大于100个 
    十进制位)的函数。据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大 
    素数的积。 

      密钥对的产生。选择两个大素数,p 和q 。计算:n = p * q 然后随机选择加密密钥e, 
    要求 e 和 ( p - 1 ) * ( q - 1 )互质。最后,利用Euclid 算法计算解密密钥d, 满足 
    e * d = 1 ( mod ( p - 1 ) * ( q - 1 ) )其中n和d也要互质。数e和n是公钥,d是私钥。 
    两个素数p和q不再需要,应该丢弃,不要让任何人知道。加密信息 m(二进制表示)时, 
    首先把m分成等长数据块 m1 ,m2,..., mi ,块长s,其中 2^s <= n, s 尽可能的大。对应 
    的密文是: 
ci = mi^e ( mod n ) .................( a ) 
解密时作如下计算: 
mi = ci^d ( mod n ) .................( b ) 

      RSA 可用于数字签名,方案是用 ( a ) 式签名, ( b )式验证。具体操作时考虑到安全性 
    和 m信息量较大等因素,一般是先作HASH 运算。RSA 的安全性。RSA的安全性依赖于大数 
    分解,但是否等同于大数分解一直未能得到理论上的证明,因为没有证明破解RSA就一定 
    需要作大数分解。假设存在一种无须分解大数的算法,那它肯定可以修改成为大数分解算法。 
    目前,RSA的一些变种算法已被证明等价于大数分解。不管怎样,分解n是最显然的攻击方法。 
    现在,人们已能分解140多个十进制位的大素数。因此,模数n必须选大一些,因具体适用情况而定。 
    
    由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论是软件还是硬件实现。 
    速度一直是RSA的缺陷。一般来说只用于少量数据加密。 
*/
 
    
public struct RSA_PARAM 
    

        
public UInt64 p, q;   //两个素数,不参与加密解密运算 
        public UInt64 f;      //f=(p-1)*(q-1),不参与加密解密运算 
        public UInt64 n, e;   //公匙,n=p*q,gcd(e,f)=1 
        public UInt64 d;      //私匙,e*d=1 (mod f),gcd(n,d)=1 
        public UInt64 s;      //块长,满足2^s<=n的最大的s,即log2(n) 
    }


    
class Program 
    

        
//小素数表 
        Prime Table 

        
readonly long g_PrimeCount = g_PrimeTable.Length; 
        
const UInt64 multiplier = 12747293821
        
const UInt64 adder = 1343545677842234541

        
//随机数类 
        public class RandNumber 
        

            
/* */ 
            
private UInt64 randSeed;/* */ 
            
public RandNumber():this(0{ } 

            
public RandNumber(UInt64 s) 
            

                
if (0 == s)//(!s) 
                
                    randSeed 
= (UInt64)new Random().Next();//time(NULL); 
                }
 
                
else 
                

                    randSeed 
= s; 
                }
 
            }
 
            
            
/* */ 
            
public UInt64 Random(UInt64 n) 
            

                randSeed 
= multiplier * randSeed + adder; 
                
return randSeed % n; 
            }
 
        }
 

        
static RandNumber g_Rnd = new RandNumber(); 

        
/* 模乘运算,返回值 x=a*b mod n */ 
        UInt64 MulMod(UInt64 a, UInt64 b, UInt64 n) 
        

            
return a * b % n; 
        }
 

        
/* 模幂运算,返回值 x=base^pow mod n */ 
        UInt64 PowMod(UInt64 bas, UInt64 pow, UInt64 n) 
        

            UInt64 a 
= bas, b = pow, c = 1
            
while (b != 0)  // (b) 
            
                
while (1 != (b & 1))    // !(b&1) 
                
                    b 
>>= 1;            //a=a * a % n;    //函数看起来可以处理64位的整数,但由于这里a*a在a>=2^32时已经造成了溢出,因此实际处理范围没有64位 
                    a = MulMod(a, a, n); 
                }
 b--;        //c=a * c % n;        //这里也会溢出,若把64位整数拆为两个32位整数不知是否可以解决这个问题。 
                c = MulMod(a, c, n); 
            }
 return c; 
        }
 

        
/* 
        Rabin-Miller素数测试,通过测试返回1,否则返回0。 
        n是待测素数。 
        注意:通过测试并不一定就是素数,非素数通过测试的概率是1/4 
        
*/
 
        
long RabinMillerKnl(UInt64 n) 
        

            UInt64 b, m, j, v, i; 
            m 
= n - 1
            j 
= 0;    //0、先计算出m、j,使得n-1=m*2^j,其中m是正奇数,j是非负整数 
            while (1 != (m&1))    // (!(m & 1)) 
            
                
++j; 
                m 
>>= 1
            }
    //1、随机取一个b,2<=b            
            b = 2 + g_Rnd.Random(n - 3);    //2、计算v=b^m mod n 
            v = PowMod( b,  m,  n);    //3、如果v==1,通过测试 
            if (v == 1
            

                
return 1
            }
    //4、令i=1 
            i = 1;    //5、如果v=n-1,通过测试 
            while

抱歉!评论已关闭.