基于私钥加密公钥解密的RSA算法C#实现方法
本文实例讲述了基于私钥加密公钥解密的rsa算法c#实现方法,是一种应用十分广泛的算法。分享给大家供大家参考之用。具体方法如下:
一、概述
rsa算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。 rsa是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。rsa的安全性依赖于大数的因子分解,但并没有从理论上证明破译rsa的难度与大数分解难度等价。
rsa的安全性依赖于大数分解。公钥和私钥都是两个大素数( 大于 100个十进制位)的函数。据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积。
密钥对的产生。选择两个大素数,p 和q 。计算:
n = p * q
然后随机选择加密密钥e(ps:最常用的e值有3,17和65537,微软就是使用的65537,采用3个中的任何一个都不存在安全问题),要求 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 )
.net提供常用的加密算法类,支持rsa的类是rsacryptoserviceprovider(命名空间:system.security.cryptography),但只支持公钥加密,私钥解密。rsacryptoserviceprovider类包括:modulus、exponent、p、q、dp、dq、inverseq、d等8个属性,其中modulus和exponent就是公钥,modulus和d就是私钥,rsacryptoserviceprovider类提供导出公钥的方法,也提供导出私钥的方法,但导出的私钥包含上面8个属性,显然要用rsacryptoserviceprovider实现私钥加密公钥是不可行的。
从rsa的原理来看,公钥加密私钥解密和私钥加密公钥解密应该是等价的,在某些情况下,比如共享软件加密,我们需要用私钥加密注册码或注册文件,发给用户,用户用公钥解密注册码或注册文件进行合法性验证。
二、实现方法
本人利用网上找的一个c#版的大整数类biginteger(本人认为这是偶发现的效率最高的一个c#版大整数类)来实现私钥加密公钥加密(事实上也完全支持公租加密私钥解密),但没有使用类biginteger的大素数生成函数,而是直接使用类rsacryptoserviceprovider来生成大素数。其中加密函数和解密函数的实现如下:
/* 功能:用指定的私钥(n,d)加密指定字符串source */ private string encryptstring(string source, biginteger d, biginteger n) { int len = source.length; int len1 = 0; int blocklen = 0; if ((len % 128) == 0) len1 = len / 128; else len1 = len / 128 + 1; string block = ""; string temp = ""; for (int i = 0; i < len1; i++) { if (len >= 128) blocklen = 128; else blocklen = len; block = source.substring(i * 128, blocklen); byte[] otext = system.text.encoding.default.getbytes(block); biginteger bitext = new biginteger(otext); biginteger bientext = bitext.modpow(d, n); string temp1 = bientext.tohexstring(); temp += temp1; len -= blocklen; } return temp; } /* 功能:用指定的公钥(n,e)解密指定字符串source */ private string decryptstring(string source, biginteger e, biginteger n) { int len = source.length; int len1 = 0; int blocklen = 0; if ((len % 256) == 0) len1 = len / 256; else len1 = len / 256 + 1; string block = ""; string temp = ""; for (int i = 0; i < len1; i++) { if (len >= 256) blocklen = 256; else blocklen = len; block = source.substring(i * 256, blocklen); biginteger bitext = new biginteger(block, 16); biginteger bientext = bitext.modpow(e, n); string temp1 = system.text.encoding.default.getstring(bientext.getbytes()); temp += temp1; len -= blocklen; } return temp; }
加密过程和解密过程代码如下所示:
/* 加密过程,其中d、n是rsacryptoserviceprovider生成的d、modulus */ private string encryptprocess(string source, string d, string n) { byte[] n = convert.frombase64string(n); byte[] d = convert.frombase64string(d); biginteger bin = new biginteger(n); biginteger bid = new biginteger(d); return encryptstring(source, bid, bin); } /* 解密过程,其中e、n是rsacryptoserviceprovider生成的exponent、modulus */ private string decryptprocess(string source, string e, string n) { byte[] n = convert.frombase64string(n); byte[] e = convert.frombase64string(e); biginteger bin = new biginteger(n); biginteger bie = new biginteger(e); return decryptstring(source, bie, bin); }
相信本文所述对大家的c#程序设计有一定的借鉴价值。