椭圆曲线密码学(Elliptic curve cryptography
![](/icons/70713dou.gif)
缩写为ECC)是基于椭圆曲线数学
![](/icons/70713de.gif)
![](/icons/70713yi.gif)
种公钥密码
![](/icons/70713de.gif)
思路方法
![](/icons/70713dou2.gif)
椭圆曲线在密码学中
![](/icons/70713de.gif)
使用是在1985年由Neal Koblitz和Victor Miller分别独立提出
![](/icons/70713de.gif)
椭圆签名算法应该是微软最先用在软件Software保护上
![](/icons/70713de.gif)
![](/icons/70713dou.gif)
我们平常用
![](/icons/70713de.gif)
25位序列号就是基于椭圆签名算法
![](/icons/70713de.gif)
![](/icons/70713dou2.gif)
理论上说
![](/icons/70713dou.gif)
椭圆签名算法是很难破解
![](/icons/70713de.gif)
![](/icons/70713dou.gif)
![](/icons/70713yinwei.gif)
...(省略
![](/icons/70713dou.gif)
感兴趣
![](/icons/70713de.gif)
可以看看
![](/icons/70713smhl.gif)
ECC加密算法入门介绍
![](/icons/70713smhr.gif)
这篇文章)
![](/icons/70713dou2.gif)
但是
![](/icons/70713yinwei.gif)
微软出于序列号长度
![](/icons/70713de.gif)
考虑
![](/icons/70713dou.gif)
签名
![](/icons/70713de.gif)
长度只有62bit(具体是多少
![](/icons/70713dou.gif)
忘了)
![](/icons/70713dou.gif)
所以可以暴力计算私钥
![](/icons/70713dou2.gif)
我们用过
![](/icons/70713de.gif)
算号器就是这样
![](/icons/70713de.gif)
定义:
椭圆曲线Ep=(p,a,b,G,n,h)
p、a、b 用来确定曲线
![](/icons/70713dou.gif)
G为基点
![](/icons/70713dou.gif)
n为点G
![](/icons/70713de.gif)
阶
![](/icons/70713dou.gif)
h是椭圆曲线上所有点
![](/icons/70713de.gif)
个数m和n相除
![](/icons/70713de.gif)
整数部分
签名过程
1
![](/icons/70713dou.gif)
选择
![](/icons/70713yi.gif)
条椭圆曲线Ep(a,b)
![](/icons/70713dou.gif)
和基点G
2
![](/icons/70713dou.gif)
选择私有密钥k(k<n,n为G
![](/icons/70713de.gif)
阶)
![](/icons/70713dou.gif)
利用基点G计算公开密钥K=kG
3
![](/icons/70713dou.gif)
取
![](/icons/70713yi.gif)
个随机整数r(r<n),计算点R=rG
4
![](/icons/70713dou.gif)
计算特征信息和R
![](/icons/70713de.gif)
散列值
![](/icons/70713dou.gif)
即Hash=SHA(data,x,y)
5
![](/icons/70713dou.gif)
计算sig≡r-Hash*k(mod n)
6
![](/icons/70713dou.gif)
使用sig和Hash生成序列号(例如使用BASE24编码)
验证过程
1
![](/icons/70713dou.gif)
从序列号中提取sig和Hash
2
![](/icons/70713dou.gif)
计算R≡sig*G+Hash*K (mod p)
3
![](/icons/70713dou.gif)
计算计算特征信息和R
![](/icons/70713de.gif)
散列值
![](/icons/70713dou.gif)
即H=SHA(data,x,y)
4
![](/icons/70713dou.gif)
比较H和Hash
实际上
![](/icons/70713dou.gif)
上述过程就是Elliptic Curve DSA (ECDSA)
好吧
![](/icons/70713dou.gif)
言归正传
![](/icons/70713dou.gif)
我们如何在c#中使用椭圆签名算法呢?
在.Net3.5中
![](/icons/70713dou.gif)
微软提供了ECDsaCng类
![](/icons/70713dou.gif)
但是局限性是必须在Vista系统上才能使用
![](/icons/70713dou.gif)
另外就是微软
![](/icons/70713de.gif)
实现事先为我们确定了椭圆曲线
![](/icons/70713de.gif)
参数(ECDsaP256,ECDsaP384,ECDsaP521)
![](/icons/70713dou.gif)
我们没有办法使用自己
![](/icons/70713de.gif)
参数
![](/icons/70713dou2.gif)
有关ECDsaCng类
![](/icons/70713de.gif)
使用
![](/icons/70713dou.gif)
已经有人做了介绍
![](/icons/70713dou.gif)
MSDN里也有介绍说明
![](/icons/70713dou2.gif)
这里我要说
![](/icons/70713de.gif)
是如何使用第 3方类库
这里介绍
![](/icons/70713de.gif)
第 3方加密类库是BCCCrypto(http://www.bouncycastle.org/csharp/)
![](/icons/70713dou.gif)
现在
![](/icons/70713de.gif)
版本是1.4
![](/icons/70713dou.gif)
经过测试比较稳定
签名
Code
1 // 生成R=r*G
2 TBCryptoBigInteger r = null;
3 Random random =
![](/icons/70713new.gif)
SecureRandom
![](/icons/70713kh.gif)
;
4 do // Generate r
5 {
6 r =
![](/icons/70713new.gif)
TBCryptoBigInteger(this.ecdo
![](/icons/70713main.gif)
psCDKey.N.BitLength, random);
7 }
8 while (r.SignValue
![](/icons/70713dd.gif)
0);
9 ECPo
![](/icons/70713int.gif)
R = this.ecdo
![](/icons/70713main.gif)
psCDKey.G.Multiply(r);
10 // Hash = SHA1(data,Rx,Ry)
11
![](/icons/70713string.gif)
hashStr = Sha1(31, rawKeyBytes, R.X.ToBigInteger
![](/icons/70713kh.gif)
.ToByteArray
![](/icons/70713kh.gif)
, R.Y.ToBigInteger
![](/icons/70713kh.gif)
.ToByteArray
![](/icons/70713kh.gif)
);
12 TBCryptoBigInteger hashInt =
![](/icons/70713new.gif)
TBCryptoBigInteger(hashStr, 2);
13 // sig = r-Hash*D (mod n)
14 TBCryptoBigInteger sig = r.Subtract(hashInt.Multiply(this.ecDCDKey)).Mod(this.ecdo
![](/icons/70713main.gif)
psCDKey.N);
验证
Code
1 // 验证签名
2 X9ECParameters ecps = X962NamedCurves.GetByOid(X9ObjectIdent
![](/icons/70713if.gif)
iers.Prime256v1);
3 ECPublicKeyParameters pk =
![](/icons/70713new.gif)
ECPublicKeyParameters("ECDSA",
4 ecps.Curve.DecodePo
![](/icons/70713int.gif)
(Hex.Decode(KeyAttribute.GetKey(type.Assembly))),
5
![](/icons/70713new.gif)
ECDo
![](/icons/70713main.gif)
Parameters(ecps.Curve, ecps.G, ecps.N, ecps.H));
6 ISigner s = SignerUtilities.GetSigner("ECDSA");
7 s.Init(false, pk);
8 s.BlockUpdate(
![](/icons/70713byte.gif)
s, 0, dataLen);
9
![](/icons/70713if.gif)
(s.Ver
![](/icons/70713if.gif)
ySignature(sig))
10 {
11 this.data =
![](/icons/70713byte.gif)
[dataLen];
12 Array.Copy(
![](/icons/70713byte.gif)
s, 0, this.data, 0, data.Length);
13 }