加密算法入门介绍

前言
同RSA(Ron Rivest,Adi Shamir,Len Adleman三位天才的名字)一样,ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)也属于公开密钥算法。目前,国内详细介绍ECC的公开文献并不多(反正我没有找到)。有一些简介,也是泛泛而谈,看完后依然理解不了ECC的实质(可能我理解力太差)。前些天我从国外网站找到些材料,看完后对ECC似乎懵懂了。于是我想把我对ECC的认识整理一下,与大家分享。当然ECC博大精深,我的认识还很肤浅,文章中错误一定不少,欢迎各路高手批评指正,小弟我洗耳恭听,并及时改正。文章将采用连载的方式,我写好一点就贴出来一点。本文主要侧重理论,代码实现暂不涉及。这就要求你要有一点数学功底。最好你能理解RSA算法,对公开密钥算法有一个了解。《近世代数基础》《初等数论》之类的书,最好您先翻一下,这对您理解本文是有帮助的。别怕,我尽量会把语言通俗些,希望本文能成为学习ECC的敲门砖。
一、从平行线谈起。
平行线,永不相交。没有人怀疑把:)不过到了近代这个结论遭到了质疑。平行线会不会在很远很远的地方相交了?事实上没有人见到过。所以“平行线,永不相交”只是假设(大家想想初中学习的平行公理,是没有证明的)。既然可以假设平行线永不相交,也可以假设平行线在很远很远的地方相交了。即平行线相交于无穷远点P∞(请大家闭上眼睛,想象一下那个无穷远点P∞,P∞是不是很虚幻,其实与其说数学锻炼人的抽象能力,还不如说是锻炼人的想象力)。给个图帮助理解一下:

直线上出现P∞点,所带来的好处是所有的直线都相交了,且只有一个交点。这就把直线的平行与相交统一了。为与无穷远点相区别把原来平面上的点叫做平常点。
以下是无穷远点的几个性质。
▲直线L上的无穷远点只能有一个。(从定义可直接得出)
▲平面上一组相互平行的直线有公共的无穷远点。(从定义可直接得出)
▲ 平面上任何相交的两直线L1,L2有不同的无穷远点。(否则L1和L2有公共的无穷远点P,则L1和L2有两个交点A、P,故假设错误。)
▲平面上全体无穷远点构成一条无穷远直线。(自己想象一下这条直线吧)
▲平面上全体无穷远点与全体平常点构成射影平面。
二、射影平面坐标系
射影平面坐标系是对普通平面直角坐标系(就是我们初中学到的那个笛卡儿平面直角坐标系)的扩展。我们知道普通平面直角坐标系没有为无穷远点设计坐标,不能表示无穷远点。为了表示无穷远点,产生了射影平面坐标系,当然射影平面坐标系同样能很好的表示旧有的平常点(数学也是“向下兼容”的)。

我们对普通平面直角坐标系上的点A的坐标(x,y)做如下改造:
令x=X/Z ,y=Y/Z(Z≠0);则A点可以表示为(X:Y:Z)。
变成了有三个参量的坐标点,这就对平面上的点建立了一个新的坐标体系。
例2.1:求点(1,2)在新的坐标体系下的坐标。
解:∵X/Z=1 ,Y/Z=2(Z≠0)∴X=Z,Y=2Z ∴坐标为(Z:2Z:Z),Z≠0。即(1:2:1)(2:4:2)(1.2:2.4:1.2)等形如(Z:2Z:Z),Z≠0的坐标,都是(1,2)在新的坐标体系下的坐标。
我们也可以得到直线的方程aX+bY+cZ=0(想想为什么?提示:普通平面直角坐标系下直线一般方程是ax+by+c=0)。新的坐标体系能够表示无穷远点么?那要让我们先想想无穷远点在哪里。根据上一节的知识,我们知道无穷远点是两条平行直线的交点。那么,如何求两条直线的交点坐标?这是初中的知识,就是将两条直线对应的方程联立求解。平行直线的方程是:
aX+bY+c1Z =0; aX+bY+c2Z =0 (c1≠c2);
(为什么?提示:可以从斜率考虑,因为平行线斜率相同);
将二方程联立,求解。有c2Z= c1Z= -(aX+bY),∵c1≠c2 ∴Z=0 ∴aX+bY=0;
所以无穷远点就是这种形式(X:Y:0)表示。注意,平常点Z≠0,无穷远点Z=0,因此无穷远直线对应的方程是Z=0。

例2.2:求平行线L1:X+2Y+3Z=0 与L2:X+2Y+Z=0 相交的无穷远点。
解:因为L1∥L2 所以有Z=0, X+2Y=0;所以坐标为(-2Y:Y:0),Y≠0。即(-2:1:0)(-4:2:0)(-2.4:1.2:0)等形如(-2Y:Y:0),Y≠0的坐标,都表示这个无穷远点。

看来这个新的坐标体系能够表示射影平面上所有的点,我们就把这个能够表示射影平面上所有点的坐标体系叫做射影平面坐标系。


练习:
1、求点A(2,4) 在射影平面坐标系下的坐标。
2、求射影平面坐标系下点(4.5:3:0.5),在普通平面直角坐标系下的坐标。
3、求直线X+Y+Z=0上无穷远点的坐标。
4、判断:直线aX+bY+cZ=0上的无穷远点 和 无穷远直线与直线aX+bY=0的交点,是否是同一个点?


三、椭圆曲线

上一节,我们建立了射影平面坐标系,这一节我们将在这个坐标系下建立椭圆曲线方程。因为我们知道,坐标中的曲线是可以用方程来表示的(比如:单位圆方程是x2+y2=1)。椭圆曲线是曲线,自然椭圆曲线也有方程。

椭圆曲线的定义:
一条椭圆曲线是在射影平面上满足方程
Y2Z+a1XYZ+a3YZ2=X3+a2X2Z+a4XZ2+a6Z3 ----------------[3-1]
的所有点的集合,且曲线上的每个点都是非奇异(或光滑)的。

定义详解:

▲ Y2Z+a1XYZ+a3YZ2 = X3+a2X2Z+a4XZ2+a6Z3是Weierstrass方程(维尔斯特拉斯,Karl Theodor Wilhelm Weierstrass,1815-1897),是一个齐次方程。

▲ 椭圆曲线的形状,并不是椭圆的。只是因为椭圆曲线的描述方程,类似于计算一个椭圆周长的方程(计算椭圆周长的方程,我没有见过,而对椭圆线积分(设密度为1)是求不出来的。谁知道这个方程,请告诉我呀^_^),故得名。

我们来看看椭圆曲线是什么样的。



▲ 所谓“非奇异”或“光滑”的,在数学中是指曲线上任意一点的偏导数Fx(x,y,z),Fy(x,y,z),Fz(x,y,z)不能同时为0。如果你没有学过高等数学,可以这样理解这个词,即满足方程的任意一点都存在切线。

下面两个方程都不是椭圆曲线,尽管他们是方程[3-1]的形式。


因为他们在(0:0:1)点处(即原点)没有切线。

▲椭圆曲线上有一个无穷远点O∞(0:1:0),因为这个点满足方程[3-1]。

知道了椭圆曲线上的无穷远点。我们就可以把椭圆曲线放到普通平面直角坐标系上了。因为普通平面直角坐标系只比射影平面坐标系少无穷远点。我们在普通平面直角坐标系上,求出椭圆曲线上所有平常点组成的曲线方程,再加上无穷远点O∞(0:1:0),不就构成椭圆曲线了么?

我们设x=X/Z ,y=Y/Z代入方程[3-1]得到:
y2+a1xy+a3y = x3+a2x2+a4x+a6 -------------------------[3-2]

也就是说满足方程[3-2]的光滑曲线加上一个无穷远点O∞,组成了椭圆曲线。为了方便运算,表述,以及理解,今后论述椭圆曲线将主要使用[3-2]的形式。

本节的最后,我们谈一下求椭圆曲线一点的切线斜率问题。
由椭圆曲线的定义可以知道,椭圆曲线是光滑的,所以椭圆曲线上的平常点都有切线。而切线最重要的一个参数就是斜率k。

例3.1:求椭圆曲线方程y2+a1xy+a3y=x3+a2x2+a4x+a6上,平常点A(x,y)的切线的斜率k。
解:令F(x,y)= y2+a1xy+a3y-x3-a2x2-a4x-a6
求偏导数
Fx(x,y)= a1y-3x2-2a2x-a4
Fy(x,y)= 2y+a1x +a3
则导数为:f'(x)=- Fx(x,y)/ Fy(x,y)=-( a1y-3x2-2a2x-a4)/(2y+a1x +a3)
= (3x2+2a2x+a4-a1y) /(2y+a1x +a3)
所以k=(3x2+2a2x+a4-a1y) /(2y+a1x +a3) ------------------------[3-3]

看不懂解题过程没有关系,记住结论[3-3]就可以了。


练习:
1、将给出图例的椭圆曲线方程Y2Z=X3-XZ2 和Y2Z=X3+XZ2+Z3转换成普通平面直角坐标系上的方程。


四、椭圆曲线上的加法

上一节,我们已经看到了椭圆曲线的图象,但点与点之间好象没有什么联系。我们能不能建立一个类似于在实数轴上加法的运算法则呢?天才的数学家找到了这一运算法

☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
自从近世纪代数学引入了群、环、域的概念,使得代数运算达到了高度的统一。比如数学家总结了普通加法的主要特征,提出了加群(也叫交换群,或Abel(阿贝尔)群),在加群的眼中。实数的加法和椭圆曲线的上的加法没有什么区别。这也许就是数学抽象把:)。关于群以及加群的具体概念请参考近世代数方面的数学书。
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

算法则:任意取椭圆曲线上两点P、Q (若P、Q两点重合,则做P点的切线)做直线交于椭圆曲线的另一点R’,过R’做y轴的平行线交于R。我们规定P+Q=R。(如图)



法则详解:
▲这里的+不是实数中普通的加法,而是从普通加法中抽象出来的加法,他具备普通加法的一些性质,但具体的运算法则显然与普通加法不同。

▲根据这个法则,可以知道椭圆曲线无穷远点O∞与椭圆曲线上一点P的连线交于P’,过P’作y轴的平行线交于P,所以有 无穷远点 O∞+ P = P 。这样,无穷远点 O∞的作用与普通加法中零的作用相当(0+2=2),我们把无穷远点 O∞ 称为 零元。同时我们把P’称为P的负元(简称,负P;记作,-P)。(参见下图)

▲根据这个法则,可以得到如下结论 :如果椭圆曲线上的三个点A、B、C,处于同一条直线上,那么他们的和等于零元,即A+B+C= O∞

▲k个相同的点P相加,我们记作kP。如下图:3P = P+P+P = R+P = S。

下面,我们利用P、Q点的坐标(x1,y1),(x2,y2),求出R=P+Q的坐标(x4,y4)。

例4.1:求椭圆曲线方程y2+a1xy+a3y=x3+a2x2+a4x+a6上,平常点P(x1,y1),Q(x2,y2)的和R(x4,y4)的坐标。
解:(1)先求点-R(x3,y3)
因为P,Q,-R三点共线,故设共线方程为y=kx+b,其中
若P≠Q(P,Q两点不重合) 则
直线斜率k=(y1-y2)/(x1-x2)
若P=Q(P,Q两点重合) 则直线为椭圆曲线的切线,故由例3.1可知:
k=(3x2+2a2x+a4 -a1y) /(2y+a1x+a3)

因此P,Q,-R三点的坐标值就是方程组:
y2+a1xy+a3y=x3+a2x2+a4x+a6 -----------------[1]
y=(kx+b) -----------------[2]
的解。

将[2],代入[1] 有
(kx+b)2+a1x(kx+b)+a3(kx+b) =x3+a2x2+a4x+a6 --------[3]
对[3]化为一般方程,根据三次方程根与系数关系(当三次项系数为1时;-x1x2x3 等于常数项系数, x1x2+x2x3+x3x1等于一次项系数,-(x1+x2+x3)等于二次项系数。)
所以-(x1+x2+x3)=a2-ka1-k2
x3=k2+ka1+a2+x1+x2;---------------------求出点-R的横坐标
因为k=(y1-y3)/(x1-x3) 故
y3=y1-k(x1-x3);-------------------------------求出点-R的纵坐标

(2)利用-R求R
显然有 x4=x3= k2+ka1+a2+x1+x2; ------------求出点R的横坐标
而y3 y4 为 x=x4时 方程y2+a1xy+a3y=x3+a2x2+a4x+a6的解
化为一般方程y2+(a1x+a3)y-(x3+a2x2+a4x+a6)=0 , 根据二次方程根与系数关系得:
-(a1x+a3)=y3+y4
故y4=-y3-(a1x+a3)=k(x1-x4)-y1-(a1x4+a3); ---------------求出点R的纵坐标
即:
x4=k2+ka1+a2+x1+x2;
y4=k(x1-x4)-y1-a1x4-a3;

本节的最后,提醒大家注意一点,以前提供的图像可能会给大家产生一种错觉,即椭圆曲线是关于x轴对称的。事实上,椭圆曲线并不一定关于x轴对称。如下图的y2-xy=x3+1

五、密码学中的椭圆曲线

我们现在基本上对椭圆曲线有了初步的认识,这是值得高兴的。但请大家注意,前面学到的椭圆曲线是连续的,并不适合用于加密;所以,我们必须把椭圆曲线变成离散的点。
让我们想一想,为什么椭圆曲线为什么连续?是因为椭圆曲线上点的坐标,是实数的(也就是说前面讲到的椭圆曲线是定义在实数域上的),实数是连续的,导致了曲线的连续。因此,我们要把椭圆曲线定义在有限域上(顾名思义,有限域是一种只有由有限个元素组成的域)。

☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
域的概念是从我们的有理数,实数的运算中抽象出来的,严格的定义请参考近世代数方面的数。简单的说,域中的元素同有理数一样,有自己得加法、乘法、除法、单位元(1),零元(0),并满足交换率、分配率。
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

下面,我们给出一个有限域Fp,这个域只有有限个元素。

Fp中只有p(p为素数)个元素0,1,2 …… p-2,p-1;
Fp 的加法(a+b)法则是 a+b≡c (mod p);即,(a+c)÷p的余数 和c÷p的余数相同。
Fp 的乘法(a×b)法则是 a×b≡c (mod p);
Fp 的除法(a÷b)法则是 a/b≡c (mod p);即 a×b-1≡c (mod p);(b-1也是一个0到p-1之间的整数,但满足b×b-1≡1 (mod p);具体求法可以参考初等数论,或我的另一篇文章)。
Fp 的单位元是1,零元是 0。

同时,并不是所有的椭圆曲线都适合加密。y2=x3+ax+b是一类可以用来加密的椭圆曲线,也是最为简单的一类。下面我们就把y2=x3+ax+b 这条曲线定义在Fp上:

选择两个满足下列条件的小于p(p为素数)的非负整数a、b
4a3+27b2≠0 (mod p)
则满足下列方程的所有点(x,y),再加上 无穷远点O∞ ,构成一条椭圆曲线。
y2=x3+ax+b (mod p)
其中 x,y属于0到p-1间的整数,并将这条椭圆曲线记为Ep(a,b)。

我们看一下y2=x3+x+1 (mod 23)的图像

是不是觉得不可思议?椭圆曲线,怎么变成了这般模样,成了一个一个离散的点?
椭圆曲线在不同的数域中会呈现出不同的样子,但其本质仍是一条椭圆曲线。举一个不太恰当的例子,好比是水,在常温下,是液体;到了零下,水就变成冰,成了固体;而温度上升到一百度,水又变成了水蒸气。但其本质仍是H2O。

Fp上的椭圆曲线同样有加法,但已经不能给以几何意义的解释。不过,加法法则和实数域上的差不多,请读者自行对比。

1 无穷远点 O∞是零元,有O∞+ O∞= O∞,O∞+P=P
2 P(x,y)的负元是 (x,-y),有P+(-P)= O∞
3 P(x1,y1),Q(x2,y2)的和R(x3,y3) 有如下关系:
x3≡k2-x1-x2(mod p)
y3≡k(x1-x3)-y1(mod p)
其中若P=Q 则 k=(3x2+a)/2y1 若P≠Q,则k=(y2-y1)/(x2-x1)


例5.1 已知E23(1,1)上两点P(3,10),Q(9,7),求1)-P,2)P+Q,3) 2P。
解 1) –P的值为(3,-10)
2) k=(7-10)/(9-3)=-1/2,2的乘法逆元为12 因为2*12≡1 (mod 23)
k≡-1*12 (mod 23) 故 k=11。
x=112-3-9=109≡17 (mod 23);
y=11[3-(-6)]-10=89≡20 (mod 23)
故P+Q的坐标为(17,20)
3) k=[3(32)+1]/(2*10)=1/4≡6 (mod 23)
x=62-3-3=30≡20 (mod 23)
y=6(3-7)-10=-34≡12 (mod 23)
故2P的坐标为(7,12)

最后,我们讲一下椭圆曲线上的点的阶。
如果椭圆曲线上一点P,存在最小的正整数n,使得数乘nP=O∞,则将n称为P的 阶,若n不存在,我们说P是无限阶的。
事实上,在有限域上定义的椭圆曲线上所有的点的阶n都是存在的(证明,请参考近世代数方面的书)


练习:
1 求出E11(1,6)上所有的点。
2 已知E11(1,6)上一点G(2,7),求2G到13G所有的值。


六、椭圆曲线上简单的加密/解密

公开密钥算法总是要基于一个数学上的难题。比如RSA 依据的是:给定两个素数p、q 很容易相乘得到n,而对n进行因式分解却相对困难。那椭圆曲线上有什么难题呢?

考虑如下等式:
K=kG [其中 K,G为Ep(a,b)上的点,k为小于n(n是点G的阶)的整数]
不难发现,给定k和G,根据加法法则,计算K很容易;但给定K和G,求k就相对困难了。
这就是椭圆曲线加密算法采用的难题。我们把点G称为基点(base point),k(k

现在我们描述一个利用椭圆曲线进行加密通信的过程:

1、用户A选定一条椭圆曲线Ep(a,b),并取椭圆曲线上一点,作为基点G。
2、用户A选择一个私有密钥k,并生成公开密钥K=kG。
3、用户A将Ep(a,b)和点K,G传给用户B。
4、用户B接到信息后 ,将待传输的明文编码到Ep(a,b)上一点M(编码方法很多,这里不作讨论),并产生一个随机整数r(r 5、用户B计算点C1=M+rK;C2=rG。
6、用户B将C1、C2传给用户A。
7、用户A接到信息后,计算C1-kC2,结果就是点M。因为
C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M
再对点M进行解码就可以得到明文。

在这个加密通信中,如果有一个偷窥者H ,他只能看到Ep(a,b)、K、G、C1、C2 而通过K、G 求k 或通过C2、G求r 都是相对困难的。因此,H无法得到A、B间传送的明文信息。

密码学中,描述一条Fp上的椭圆曲线,常用到六个参量:
T=(p,a,b,G,n,h)。
(p 、a 、b 用来确定一条椭圆曲线,
G为基点,
n为点G的阶,
h 是椭圆曲线上所有点的个数m与n相除的整数部分)

这几个参量取值的选择,直接影响了加密的安全性。参量值一般要求满足以下几个条件:

1、p 当然越大越安全,但越大,计算速度会变慢,200位左右可以满足一般安全要求;
2、p≠n×h;
3、pt≠1 (mod n),1≤t<20;
4、4a3+27b2≠0 (mod p);
5、n 为素数;
6、h≤4。


七、椭圆曲线在软件注册保护的应用

我们知道将公开密钥算法作为软件注册算法的好处是Cracker很难通过跟踪验证算法得到注册机。下面,将简介一种利用Fp(a,b)椭圆曲线进行软件注册的方法。


软件作者按如下方法制作注册机(也可称为签名过程)

1、选择一条椭圆曲线Ep(a,b),和基点G;
2、选择私有密钥k(k 3、产生一个随机整数r(r 4、将用户名和点R的坐标值x,y作为参数,计算SHA(Secure
Hash Algorithm 安全散列算法,类似于MD5)值,即Hash=SHA(username,x,y);
5、计算sn≡r - Hash * k (mod n)
6、将sn和Hash作为 用户名username的序列号

软件验证过程如下:(软件中存有椭圆曲线Ep(a,b),和基点G,公开密钥K)

1、从用户输入的序列号中,提取sn以及Hash
2、计算点R≡sn*G+Hash*K ( mod p ),如果sn、Hash正确,其值等于软件作者签名过程中点R(x,y)的坐标,因为
sn≡r-Hash*k (mod n)
所以
sn*G + Hash*K
=(r-Hash*k)*G+Hash*K
=rG-Hash*kG+Hash*K
=rG- Hash*K+ Hash*K
=rG=R ;
3、将用户名和点R的坐标值x,y作为参数,计算H=SHA(username,x,y);
4、如果H=Hash 则注册成功。如果H≠Hash ,则注册失败(为什么?提示注意点R与Hash的关联性)。

简单对比一下两个过程:
作者签名用到了:椭圆曲线Ep(a,b),基点G,私有密钥k,及随机数r。
软件验证用到了:椭圆曲线Ep(a,b),基点G,公开密钥K。
Cracker要想制作注册机,只能通过软件中的Ep(a,b),点G,公开密钥K ,并利用K=kG这个关系获得k后,才可以。而求k是很困难的。


练习:
下面也是一种常于软件保护的注册算法,请认真阅读,并试回答签名过程与验证过程都用到了那些参数,Cracker想制作注册机,应该如何做。

软件作者按如下方法制作注册机(也可称为签名过程)
1、选择一条椭圆曲线Ep(a,b),和基点G;
2、选择私有密钥k(k 3、产生一个随机整数r(r 4、将用户名作为参数,计算Hash=SHA(username);
5、计算 x’=x (mod n)
6、计算sn≡(Hash+x’*k)/r (mod n)
7、将sn和x’作为 用户名username的序列号

软件验证过程如下:(软件中存有椭圆曲线Ep(a,b),和基点G,公开密钥K)
1、从用户输入的序列号中,提取sn以及x’;
2、将用户名作为参数,计算Hash=SHA(username);
3、计算 R=(Hash*G+x’*K)/sn,如果sn、Hash正确,其值等于软件作者签名过程中点R(x,y),因为
sn≡(Hash+x’*k)/r (mod n)
所以
(Hash*G+x’*K)/sn
=(Hash*G+x’*K)/[(Hash+x’*k)/r]
=(Hash*G+x’*K)/[(Hash*G+x’*k*G)/(rG)]
=rG*[(Hash*G+x’*K)/(Hash*G+x’*K)]
=rG=R (mod p)
4、v≡x (mod n)
5、如果v=x’ 则注册成功。如果v≠x’ ,则注册失败。


八、结语

历经半个多月断断续续的写作,这篇拙作终于算告一段落了。为写这篇文章,我查了大量的资料,但为了使文章更通俗易懂,我尽量避免涉及专业术语,F2n域上的椭圆曲线本文也没有涉及。不过,一些名词描述的可能还不太精确,希望众读者对文章的问题,多多批评指正。我也仅仅把这篇文章作为初稿,我会不断修订他的。最后感谢看雪、Sunbird、CCG以及看雪论坛所有成员对我的支持,感谢一切帮助过我的人,没有你们的鼓励,这篇文章我是没有动力写完的,谢谢,谢谢大家!

<全文完>


主要参考文献

张禾瑞,《近世代数基础》,高等教育出版社,1978
闵嗣鹤 严士健,《初等数论》,高等教育出版社,1982
段云所,《网络信息安全》第三讲,北大计算机系
Michael Rosing ,chapter5《Implementing Elliptic Curve Cryptography》,Softbound,1998
《SEC 1: Elliptic Curve Cryptography》,Certicom Corp.,2000
《IEEE P1363a / D9》,2001
说真的,如果发贴子,要多发象“ECC加密算法入门介绍”这样的,你知道这篇文章有多珍贵!ZMWorm 曾向我询问过是否知道一些加密算法的理论出发点文章,我都以各种理由推托了。因为这些东西是受专利权严格保护的!不要说你想了解它的理论,就是用一用现成的代码都得向他缴授权费!在国外Cracker想搞到这些东西,是需要花大价钱雇商业间谍偷才能得到的!更是鲜有公布的!!!可以说这篇文章字字值千金呀!
推荐一本书《计算机密码学——计算机网络中的数据保密与安全》 卢开澄 编著 清华大学出版社
椭圆曲线密码算法介绍
一种相对比较新的技术--椭圆曲线加密系统,已经逐渐被人们用做基本的数字签名系统。
椭圆曲线作为数字签名的基本原理大致和RSA与DSA的功能相同,并且数字签名的产生与认
证的速度要比RSA和DSA快。下面我们简单的介绍一下椭圆曲线和椭圆曲线上的密码算法
1. 有限域上的椭圆曲线
设K表示一个有限域,E是域K上的椭圆曲线,则E是一个点的集合:
E/K = { ( x, y ) | y2+ a1xy + a3y = x3 + a2x2 + a4x + a6,
a1, a3, a2, a4, a6 x, y K } { O } 其中O表示无穷远点。
在E上定义‘+’运算,P + Q = R,R是过P、Q的直线与曲线的另一交点关于x轴的对称点,
当P = Q时R是P点的切线与曲线的另一交点关于x轴的对称点。这样,( E, + )构成可换群
( Abel群),O是加法单位元(零元)。
椭圆曲线离散对数问题(ECDLP)定义如下:给定定义在K上的椭圆曲线E,一个n阶的点P
E/K,和点Q E/ K,如果存在l,确定整数l, 0 l n - 1, Q = lP。我们知道,RSA是基于因
子分解,其算法的核心就是如何寻找大叔的因子分解,但ECDLP是比因子分解难得多的问题

椭圆曲线上的加法: P + Q = R
椭圆曲线上一点的2倍: P + P = R.
2. 椭圆曲线上的密码算法
基于该难题,1985年N.Koblitz和Miller提出将椭圆曲线用于密码算法,分别利用有限域上
椭圆曲线的点构成的群实现了离散对数密码算法。在《数字签名分析和实现》中详细地介
绍过的DSA算法,被广泛应用在椭圆曲线上的变化,称为椭圆曲线数字签名算法ECDSA,由
IEEE工作组和ANSI(Amercian National Standards Institute)X9组织开发。随即展开了
椭圆曲线密码学研究,除椭圆曲线外,还有人提出在其它类型的曲线如超椭圆曲线上实现
公钥密码算法。其根据是有限域上的椭圆曲线上的点群中的离散对数问题ECDLP。ECDLP是
比因子分解问题更难的问题,许多密码专家认为它是指数级的难度。从目前已知的最好求
算法来看,160比特的椭圆曲线密码算法的安全性相当于1024比特的RSA算法
此后,有人在椭圆曲线上实现了类似ElGamal的加密算法,以及可恢复明文的数字签名方案
。除有限域上的椭圆曲线密码算法外,人们还探索了在椭圆曲线上实现RSA算法,如KMOV等

3.椭圆曲线密码算法的发展
RSA算法是大家熟悉的公钥密码算法,用它可以实现数字签名,PGP软件用到的就是RSA算法
。RSA算法是基于大数的因子分解难题,由于计算水平的提高,人们逐渐可以用计算机分解
更大的数。因此RSA算法的密钥也就越来越长。在电子商务的SET协议中,规定用户使用10
24比特的RSA密钥,认证中心CA使用2048比特的RSA密钥。长密钥带来两个问题,一是运算
速度较慢,另一个是密钥存储和管理问题。如果用16位的IC卡实现电子钱包,使用1024比
特的RSA算法速度就很慢,要以秒计算。而固化RSA算法的IC卡或32位的IC卡价格则较贵。
椭圆曲线加密系统由很多依赖于离散算法问题的加密系统组成,DSA就是一个很好的例子,
成,DSA就是一个很好的例子,
DSA是以离散对数为基础的算法。椭圆曲线数字签名系统已经被研究了很多年并创造了很多
商业价值。
由于其自身优点,椭圆曲线密码学一出现便受到关注。现在密码学界普遍认为它将替代RS
A成为通用的公钥密码算法,SET( Secure Electronic Transactions )协议的制定者已把
它作为下一代SET协议中缺省的公钥密码算法,目前已成为研究的热点,是很有前途的研究
方向。
应用椭圆曲线的数字签名同时可以很容易地使用到小的有限资源的设备中例如:小卡(信
用卡大小的包含有微小处理芯片的塑料卡片)。椭圆曲线上的密码算法速度很快,分别在
32位的PC机上和16位微处理器上实现了快速的椭圆曲线密码算法,其中16位微处理器上的
EDSA数字签名不足500ms。

--------------------------------------------------------------------------------
yutian 回复于:2004-04-12 10:01:41
ElGamal算法

  ElGamal算法既能用于数据加密也能用于数字签名,其安全性依赖于计算有限域上离散对数这一难题。
密钥对产生办法。首先选择一个素数p,两个随机数, g 和x,g, x < p, 计算 y = g^x ( mod p ),则其公钥为 y, g 和p。私钥是x。g和p可由一组用户共享。
ElGamal用于数字签名。被签信息为M,首先选择一个随机数k, k与 p - 1互质,计算

a = g^k ( mod p )
再用扩展 Euclidean 算法对下面方程求解b:

M = xa + kb ( mod p - 1 )

签名就是( a, b )。随机数k须丢弃。
验证时要验证下式:

y^a * a^b ( mod p ) = g^M ( mod p )

同时一定要检验是否满足1<= a < p。否则签名容易伪造。
ElGamal用于加密。被加密信息为M,首先选择一个随机数k,k与 p - 1互质,计算

a = g^k ( mod p )
b = y^k M ( mod p )


( a, b )为密文,是明文的两倍长。解密时计算

M = b / a^x ( mod p )

  ElGamal签名的安全性依赖于乘法群(IFp)* 上的离散对数计算。素数p必须足够大,且p-1至少包含一个大素数
因子以抵抗Pohlig & Hellman算法的攻击。M一般都应采用信息的HASH值(如SHA算法)。ElGamal的安全性主要依赖于p和g,若选取不当则签名容易伪造,应保证g对于p-1的大素数因子不可约。D.Bleichenbache“GeneratingElGamal Signatures Without Knowing the Secret Key”中提到了一些攻击方法和对策。ElGamal的一个不足之处是它的密文成倍扩张。

  美国的DSS(Digital Signature Standard)的DSA(Digital Signature Algorithm)算法是经ElGamal算法
变而来。

--------------------------------------------------------------------------------
RSA算法

  它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, Adi Shamir 和Leonard Adleman。但RSA的安全性一直未能得到理论上的证明。它经历了各种攻击,至今未被完全攻破。

一、RSA算法 :

首先, 找出三个数, p, q, r,
其中 p, q 是两个相异的质数, r 是与 (p-1)(q-1) 互质的数......
p, q, r 这三个数便是 private key

接著, 找出 m, 使得 rm == 1 mod (p-1)(q-1).....
这个 m 一定存在, 因为 r 与 (p-1)(q-1) 互质, 用辗转相除法就可以得到了.....
再来, 计算 n = pq.......
m, n 这两个数便是 public key

编码过程是, 若资料为 a, 将其看成是一个大整数, 假设 a < n....
如果 a >= n 的话, 就将 a 表成 s 进位 (s <= n, 通常取 s = 2^t),
则每一位数均小於 n, 然後分段编码......
接下来, 计算 b == a^m mod n, (0 <= b < n),
b 就是编码後的资料......

解码的过程是, 计算 c == b^r mod pq (0 <= c < pq),
於是乎, 解码完毕...... 等会会证明 c 和 a 其实是相等的 :)

如果第三者进行窃听时, 他会得到几个数: m, n(=pq), b......
他如果要解码的话, 必须想办法得到 r......
所以, 他必须先对 n 作质因数分解.........
要防止他分解, 最有效的方法是找两个非常的大质数 p, q,
使第三者作因数分解时发生困难.........


<定理>
若 p, q 是相异质数, rm == 1 mod (p-1)(q-1),
a 是任意一个正整数, b == a^m mod pq, c == b^r mod pq,
则 c == a mod pq

证明的过程, 会用到费马小定理, 叙述如下:
m 是任一质数, n 是任一整数, 则 n^m == n mod m
(换另一句话说, 如果 n 和 m 互质, 则 n^(m-1) == 1 mod m)
运用一些基本的群论的知识, 就可以很容易地证出费马小定理的........

<证明>
因为 rm == 1 mod (p-1)(q-1), 所以 rm = k(p-1)(q-1) + 1, 其中 k 是整数
因为在 modulo 中是 preserve 乘法的
(x == y mod z and u == v mod z => xu == yv mod z),
所以, c == b^r == (a^m)^r == a^(rm) == a^(k(p-1)(q-1)+1) mod pq

1. 如果 a 不是 p 的倍数, 也不是 q 的倍数时,
则 a^(p-1) == 1 mod p (费马小定理) => a^(k(p-1)(q-1)) == 1 mod p
a^(q-1) == 1 mod q (费马小定理) => a^(k(p-1)(q-1)) == 1 mod q
所以 p, q 均能整除 a^(k(p-1)(q-1)) - 1 => pq | a^(k(p-1)(q-1)) - 1
即 a^(k(p-1)(q-1)) == 1 mod pq
=> c == a^(k(p-1)(q-1)+1) == a mod pq

2. 如果 a 是 p 的倍数, 但不是 q 的倍数时,
则 a^(q-1) == 1 mod q (费马小定理)
=> a^(k(p-1)(q-1)) == 1 mod q
=> c == a^(k(p-1)(q-1)+1) == a mod q
=> q | c - a
因 p | a
=> c == a^(k(p-1)(q-1)+1) == 0 mod p
=> p | c - a
所以, pq | c - a => c == a mod pq

3. 如果 a 是 q 的倍数, 但不是 p 的倍数时, 证明同上

4. 如果 a 同时是 p 和 q 的倍数时,
则 pq | a
=> c == a^(k(p-1)(q-1)+1) == 0 mod pq
=> pq | c - a
=> c == a mod pq
Q.E.D.


这个定理说明 a 经过编码为 b 再经过解码为 c 时, a == c mod n (n = pq)....
但我们在做编码解码时, 限制 0 <= a < n, 0 <= c < n,
所以这就是说 a 等於 c, 所以这个过程确实能做到编码解码的功能.....

二、RSA 的安全性

RSA的安全性依赖于大数分解,但是否等同于大数分解一直未能得到理论上的证明,因为没有证明破解 RSA就一定需要作大数分解。假设存在一种无须分解大数的算法,那它肯定可以修改成为大数分解算法。目前, RSA 的一些变种算法已被证明等价于大数分解。不管怎样,分解n是最显然的攻击方法。现在,人们已能分解多个十进制位的大素数。因此,模数n 必须选大一些,因具体适用情况而定。

三、RSA的速度

由于进行的都是大数计算,使得RSA最快的情况也比DES慢上倍,无论是软件还是硬件实现。速度一直是RSA的缺陷。一般来说只用于少量数据加密。

四、RSA的选择密文攻击

RSA在选择密文攻击面前很脆弱。一般攻击者是将某一信息作一下伪装( Blind),让拥有私钥的实体签署。然后,经过计算就可得到它所想要的信息。实际上,攻击利用的都是同一个弱点,即存在这样一个事实:乘幂保留了输入的乘法结构:

( XM )^d = X^d *M^d mod n

前面已经提到,这个固有的问题来自于公钥密码系统的最有用的特征--每个人都能使用公钥。但从算法上无法解决这一问题,主要措施有两条:一条是采用好的公钥协议,保证工作过程中实体不对其他实体任意产生的信息解密,不对自己一无所知的信息签名;另一条是决不对陌生人送来的随机文档签名,签名时首先使用One-Way HashFunction 对文档作HASH处理,或同时使用不同的签名算法。在中提到了几种不同类型的攻击方法。

五、RSA的公共模数攻击

若系统中共有一个模数,只是不同的人拥有不同的e和d,系统将是危险的。最普遍的情况是同一信息用不同的公钥加密,这些公钥共模而且互质,那末该信息无需私钥就可得到恢复。设P为信息明文,两个加密密钥为e1和e2,公共模数是n,则:

C1 = P^e1 mod n

C2 = P^e2 mod n

密码分析者知道n、e1、e2、C1和C2,就能得到P。

因为e1和e2互质,故用Euclidean算法能找到r和s,满足:

r * e1 + s * e2 = 1

假设r为负数,需再用Euclidean算法计算C1^(-1),则

( C1^(-1) )^(-r) * C2^s = P mod n

另外,还有其它几种利用公共模数攻击的方法。总之,如果知道给定模数的一对e和d,一是有利于攻击者分解模数,一是有利于攻击者计算出其它成对的e’和d’,而无需分解模数。解决办法只有一个,那就是不要共享模数n。

RSA的小指数攻击。 有一种提高 RSA速度的建议是使公钥e取较小的值,这样会使加密变得易于实现,速度有
所提高。但这样作是不安全的,对付办法就是e和d都取较大的值。

RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价。即RSA的重大缺陷是无法从理论上把握它的保密性能如何,而且密码学界多数人士倾向于因子分解不是NPC问题。 RSA的缺点主要有:A)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。B)分组长度太大,为保证安全性,n 至少也要 600 bits 以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,SET( Secure Electronic Transaction )协议中要求CA采用比特长的密钥,其他实体使用比特的密钥。

--------------------------------------------------------------------------------
DSA算法

  Digital Signature Algorithm (DSA)是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。算法中应用了下述参数:

p:L bits长的素数。L是64的倍数,范围是512到1024;
q:p - 1的160bits的素因子;
g:g = h^((p-1)/q) mod p,h满足h < p - 1, h^((p-1)/q) mod p > 1;
x:x < q,x为私钥 ;
y:y = g^x mod p ,( p, q, g, y )为公钥;
H( x ):One-Way Hash函数。DSS中选用SHA( Secure Hash Algorithm )。
p, q, g可由一组用户共享,但在实际应用中,使用公共模数可能会带来一定的威胁。签名及验证协议如下:

1. P产生随机数k,k < q;
2. P计算 r = ( g^k mod p ) mod q
s = ( k^(-1) (H(m) + xr)) mod q
签名结果是( m, r, s )。
3. 验证时计算 w = s^(-1)mod q
u1 = ( H( m ) * w ) mod q
u2 = ( r * w ) mod q
v = (( g^u1 * y^u2 ) mod p ) mod q
若v = r,则认为签名有效。

  DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。DSA的一个重要特点是两个素数公开,这
样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA算法却作不到。

--------------------------------------------------------------------------------
一、DES算法

  美国国家标准局1973年开始研究除国防部外的其它部门的计算机系统的数据加密标准,于1973年5月15日和1974年8月27日先后两次向公众发出了征求加密算法的公告。加密算法要达到的目的(通常称为DES 密码算法要求)主要为以下四点: ☆提供高质量的数据保护,防止数据未经授权的泄露和未被察觉的修改;

☆具有相当高的复杂性,使得破译的开销超过可能获得的利益,同时又要便于理解和掌握;

☆DES密码体制的安全性应该不依赖于算法的保密,其安全性仅以加密密钥的保密为基础;

☆实现经济,运行有效,并且适用于多种完全不同的应用。


1977年1月,美国政府颁布:采纳IBM公司设计的方案作为非机密数据的正式数据加密标准(DES棗Data Encryption Standard)。

  目前在国内,随着三金工程尤其是金卡工程的启动,DES算法在POS、ATM、磁卡及智能卡(IC卡)、加油站、高速公路收费站等领域被广泛应用,以此来实现关键数据的保密,如信用卡持卡人的PIN的加密传输,IC卡与POS间的双向认证、金融交易数据包的MAC校验等,均用到DES算法
  DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。
  DES算法是这样工作的:如Mode为加密,则用Key 去把数据Data进行加密, 生成Data的密码形式(64位)作为DES的输出结果;如Mode为解密,则用Key去把密码形式的数据Data解密,还原为Data的明码形式(64位)作为DES的输出结果。在通信网络的两端,双方约定一致的Key,在通信的源点用Key对核心数据进行DES加密,然后以密码形式在公共通信网(如电话网)中传输到通信网络的终点,数据到达目的地后,用同样的Key对密码数据进行解密,便再现了明码形式的核心数据。这样,便保证了核心数据(如PIN、MAC等)在公共通信网中传输的安全性和可靠性。
  通过定期在通信网络的源端和目的端同时改用新的Key,便能更进一步提高数据的保密性,这正是现在金融交易网络的流行做法。
  DES算法详述
  DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,整个算法的主流程图如下:
其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则见下表:
58,50,12,34,26,18,10,2,60,52,44,36,28,20,12,4,
  62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,
  57,49,41,33,25,17, 9,1,59,51,43,35,27,19,11,3,
  61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7,
  即将输入的第58位换到第一位,第50位换到第2位,...,依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0 是右32位,例:设置换前的输入值为D1D2D3......D64,则经过初始置换后的结果为:L0=D58D50...D8;R0=D57D49...D7。
  经过16次迭代运算后。得到L16、R16,将此作为输入,进行逆置换,即得到密文输出。逆置换正好是初始置的逆运算,例如,第1位经过初始置换后,处于第40位,而通过逆置换,又将第40位换回到第1位,其逆置换规则如下表所示:
  40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31,
  38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,
  36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,
  34,2,42,10,50,18,58 26,33,1,41, 9,49,17,57,25,
放大换位表
  32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10,11,
  12,13,12,13,14,15,16,17,16,17,18,19,20,21,20,21,
  22,23,24,25,24,25,26,27,28,29,28,29,30,31,32, 1,
单纯换位表
  16,7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10,
  2,8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25,
  在f(Ri,Ki)算法描述图中,S1,S2...S8为选择函数,其功能是把6bit数据变为4bit数据。下面给出选择函数Si(i=1,2......8)的功能表:
选择函数Si
S1:
  14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,
  0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,
  4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,
  15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13,
S2:
  15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10,
  3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5,
  0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,
  13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9,
S3:
  10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8,
  13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1,
  13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,
  1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12,
S4:
  7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15,
  13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9,
  10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,
  3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14,
S5:
  2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9,
  14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6,
  4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,
  11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3,
S6:
  12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11,
  10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8,
  9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,
  4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13,
S7:
  4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1,
  13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6,
  1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,
  6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12,
S8:
  13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7,
  1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2,
  7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,
  2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11,
在此以S1为例说明其功能,我们可以看到:在S1中,共有4行数据,命名为0,1、2、3行;每行有16列,命名为0、1、2、3,......,14、15列。
  现设输入为: D=D1D2D3D4D5D6
令:列=D2D3D4D5
  行=D1D6
  然后在S1表中查得对应的数,以4位二进制表示,此即为选择函数S1的输出。下面给出子密钥Ki(48bit)的生成算法
  从子密钥Ki的生成算法描述图中我们可以看到:初始Key值为64位,但DES算法规定,其中第8、16、......64位是奇偶校验位,不参与DES运算。故Key 实际可用位数便只有56位。即:经过缩小选择换位表1的变换后,Key 的位数由64 位变成了56位,此56位分为C0、D0两部分,各28位,然后分别进行第1次循环左移,得到C1、D1,将C1(28位)、D1(28位)合并得到56位,再经过缩小选择换位2,从而便得到了密钥K0(48位)。依此类推,便可得到K1、K2、......、K15,不过需要注意的是,16次循环左移对应的左移位数要依据下述规则进行:
循环左移位数
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
  以上介绍了DES算法的加密过程。DES算法的解密过程是一样的,区别仅仅在于第一次迭代时用子密钥K15,第二次K14、......,最后一次用K0,算法本身并没有任何变化。


二、DES算法理论图解

DES的算法是对称的,既可用于加密又可用于解密。下图是它的算法粗框图。其具体运算过程有如下七步。
<缺:找到补上>

三、DES算法的应用误区 


  DES算法具有极高安全性,到目前为止,除了用穷举搜索法对DES算法进行攻击外,还没有发现更有效的办法。而56位长的密钥的穷举空间为256,这意味着如果一台计算机的速度是每一秒种检测一百万个密钥,则它搜索完全部密钥就需要将近2285年的时间,可见,这是难以实现的,当然,随着科学技术的发展,当出现超高速计算机后,我们可考虑把DES密钥的长度再增长一些,以此来达到更高的保密程度。
  由上述DES算法介绍我们可以看到:DES算法中只用到64位密钥中的其中56位,而第8、16、24、......64位8个位并未参与DES运算,这一点,向我们提出了一个应用上的要求,即DES的安全性是基于除了8,16,24,......64位外的其余56位的组合变化256才得以保证的。因此,在实际应用中,我们应避开使用第8,16,24,......64位作为有效数据位,而使用其它的56位作为有效数据位,才能保证DES算法安全可靠地发挥作用。如果不了解这一点,把密钥Key的8,16,24,..... .64位作为有效数据使用,将不能保证DES加密数据的安全性,对运用DES来达到保密作用的系统产生数据被破译的危险,这正是DES算法在应用上的误区,留下了被人攻击、被人破译的极大隐患。

--------------------------------------------------------------------------------
DSA算法

  Digital Signature Algorithm (DSA)是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。算法中应用了下述参数:

p:L bits长的素数。L是64的倍数,范围是512到1024;
q:p - 1的160bits的素因子;
g:g = h^((p-1)/q) mod p,h满足h < p - 1, h^((p-1)/q) mod p > 1;
x:x < q,x为私钥 ;
y:y = g^x mod p ,( p, q, g, y )为公钥;
H( x ):One-Way Hash函数。DSS中选用SHA( Secure Hash Algorithm )。
p, q, g可由一组用户共享,但在实际应用中,使用公共模数可能会带来一定的威胁。签名及验证协议如下:

1. P产生随机数k,k < q;
2. P计算 r = ( g^k mod p ) mod q
s = ( k^(-1) (H(m) + xr)) mod q
签名结果是( m, r, s )。
3. 验证时计算 w = s^(-1)mod q
u1 = ( H( m ) * w ) mod q
u2 = ( r * w ) mod q
v = (( g^u1 * y^u2 ) mod p ) mod q
若v = r,则认为签名有效。

  DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。DSA的一个重要特点是两个素数公开,这
样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA算法却作不到。

--------------------------------------------------------------------------------
MD5算法

在一些初始化处理后,MD5以512位分组来处理输入文本,每一分组又划分为16个32位子分组。算法的输出由四个32位分组组成,将它们级联形成一个128位散列值。
首先填充消息使其长度恰好为一个比512位的倍数仅小64位的数。填充方法是附一个1在消息后面,后接所要求的多个0,然后在其后附上64位的消息长度(填充前)。这两步的作用是使消息长度恰好是512位的整数倍(算法的其余部分要求如此),同时确保不同的消息在填充后不相同。
四个32位变量初始化为:
A=0x01234567
B=0x89abcdef
C=0xfedcba98
D=0x76543210
它们称为链接变量(chaining variable)
接着进行算法的主循环,循环的次数是消息中512位消息分组的数目。
将上面四个变量复制到别外的变量中:A到a,B到b,C到c,D到d。
主循环有四轮(MD4只有三轮),每轮很相拟。第一轮进行16次操作。每次操作对a,b,c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上a,b,c或d中之一。最后用该结果取代a,b,c或d中之一。
以一下是每次操作中用到的四个非线性函数(每轮一个)。
F(X,Y,Z)=(X&Y)|((~X)&Z)
G(X,Y,Z)=(X&Z)|(Y&(~Z))
H(X,Y,Z)=X^Y^Z
I(X,Y,Z)=Y^(X|(~Z))
(&是与,|是或,~是非,^是异或)
这些函数是这样设计的:如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。
函数F是按逐位方式操作:如果X,那么Y,否则Z。函数H是逐位奇偶操作符。
设Mj表示消息的第j个子分组(从0到15),<第一轮
FF(a,b,c,d,M0,7,0xd76aa478)
FF(d,a,b,c,M1,12,0xe8c7b756)
FF(c,d,a,b,M2,17,0x242070db)
FF(b,c,d,a,M3,22,0xc1bdceee)
FF(a,b,c,d,M4,7,0xf57c0faf)
FF(d,a,b,c,M5,12,0x4787c62a)
FF(c,d,a,b,M6,17,0xa8304613)
FF(b,c,d,a,M7,22,0xfd469501)
FF(a,b,c,d,M8,7,0x698098d8)
FF(d,a,b,c,M9,12,0x8b44f7af)
FF(c,d,a,b,M10,17,0xffff5bb1)
FF(b,c,d,a,M11,22,0x895cd7be)
FF(a,b,c,d,M12,7,0x6b901122)
FF(d,a,b,c,M13,12,0xfd987193)
FF(c,d,a,b,M14,17,0xa679438e)
FF(b,c,d,a,M15,22,0x49b40821)
第二轮
GG(a,b,c,d,M1,5,0xf61e2562)
GG(d,a,b,c,M6,9,0xc040b340)
GG(c,d,a,b,M11,14,0x265e5a51)
GG(b,c,d,a,M0,20,0xe9b6c7aa)
GG(a,b,c,d,M5,5,0xd62f105d)
GG(d,a,b,c,M10,9,0x02441453)
GG(c,d,a,b,M15,14,0xd8a1e681)
GG(b,c,d,a,M4,20,0xe7d3fbc8)
GG(a,b,c,d,M9,5,0x21e1cde6)
GG(d,a,b,c,M14,9,0xc33707d6)
GG(c,d,a,b,M3,14,0xf4d50d87)
GG(b,c,d,a,M8,20,0x455a14ed)
GG(a,b,c,d,M13,5,0xa9e3e905)
GG(d,a,b,c,M2,9,0xfcefa3f8)
GG(c,d,a,b,M7,14,0x676f02d9)
GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三轮
HH(a,b,c,d,M5,4,0xfffa3942)
HH(d,a,b,c,M8,11,0x8771f681)
HH(c,d,a,b,M11,16,0x6d9d6122)
HH(b,c,d,a,M14,23,0xfde5380c)
HH(a,b,c,d,M1,4,0xa4beea44)
HH(d,a,b,c,M4,11,0x4bdecfa9)
HH(c,d,a,b,M7,16,0xf6bb4b60)
HH(b,c,d,a,M10,23,0xbebfbc70)
HH(a,b,c,d,M13,4,0x289b7ec6)
HH(d,a,b,c,M0,11,0xeaa127fa)
HH(c,d,a,b,M3,16,0xd4ef3085)
HH(b,c,d,a,M6,23,0x04881d05)
HH(a,b,c,d,M9,4,0xd9d4d039)
HH(d,a,b,c,M12,11,0xe6db99e5)
HH(c,d,a,b,M15,16,0x1fa27cf8)
HH(b,c,d,a,M2,23,0xc4ac5665)
第四轮
II(a,b,c,d,M0,6,0xf4292244)
II(d,a,b,c,M7,10,0x432aff97)
II(c,d,a,b,M14,15,0xab9423a7)
II(b,c,d,a,M5,21,0xfc93a039)
II(a,b,c,d,M12,6,0x655b59c3)
II(d,a,b,c,M3,10,0x8f0ccc92)
II(c,d,a,b,M10,15,0xffeff47d)
II(b,c,d,a,M1,21,0x85845dd1)
II(a,b,c,d,M8,6,0x6fa87e4f)
II(d,a,b,c,M15,10,0xfe2ce6e0)
II(c,d,a,b,M6,15,0xa3014314)
II(b,c,d,a,M13,21,0x4e0811a1)
II(a,b,c,d,M4,6,0xf7537e82)
II(d,a,b,c,M11,10,0xbd3af235)
II(c,d,a,b,M2,15,0x2ad7d2bb)
II(b,c,d,a,M9,21,0xeb86d391)
常数ti可以如下选择:
在第i步中,ti是4294967296*abs(sin(i))的整数部分,i的单位是弧度。
(2的32次方)
所有这些完成之后,将A,B,C,D分别加上a,b,c,d。然后用下一分组数据继续运行算法,最后的输出是A,B,C和D的级联。
MD5的安全性

MD5相对MD4所作的改进:
1.增加了第四轮.
2.每一步均有唯一的加法常数.
3.为减弱第二轮中函数G的对称性从(X&Y)|(X&Z)|(Y&Z)变为(X&Z)|(Y&(~Z))
4.第一步加上了上一步的结果,这将引起更快的雪崩效应.
5.改变了第二轮和第三轮中访问消息子分组的次序,使其更不相似.
6.近似优化了每一轮中的循环左移位移量以实现更快的雪崩效应.各轮的位移量互不相同.

--------------------------------------------------------------------------------
BLOWFISH算法

作 者:夜月
联 系:
[email protected]
时 间:2001年10月6日
范 例:BlowFish's CrackMe1
注册机:Bfkeygen

一、BlowFish算法说明(文中数据类型以Tc2.0为准)

  BlowFish算法用来加密64Bit长度的字符串。
BlowFish算法使用两个“盒”——ungigned long pbox[18]和unsigned long sbox[4,256]。
BlowFish算法中,有一个核心加密函数:BF_En(后文详细介绍)。该函数输入64位信息,运算后, 以64位密文的形式输出。 用BlowFish算法加密信息,需要两个过程:

1.密钥预处理
2.信息加密

分别说明如下:
密钥预处理:
BlowFish算法的源密钥——pbox和sbox是固定的。我们要加密一个信息,需要自己选择一个key, 用这个key对pbox和sbox进行变换,得到下一步信息加密所要用的key_pbox和key_sbox。具体的变化算法如下:

1)用sbox填充key_sbox
2)用自己选择的key8个一组地去异或pbox,用异或的结果填充key_pbox。key可以循环使用。
比如说:选的key是"abcdefghijklmn"。则异或过程为:
key_pbox[0]=pbox[0]^abcdefgh
key_pbox[1]=pbox[1]^ijklmnab
…………
…………
如此循环,直到key_box填充完毕。
3)用BF_En加密一个全0的64位信息,用输出的结果替换key_pbox[0]和key_pbox[1]。i=0
4)用BF_En加密替换后的key_pbox[i],key_pbox[i+1],用输出替代key_pbox[i+2]和key_pbox[i+3]
5)i+2,继续第4步,直到key_pbox全部被替换
6)用key_pbox[16]和key_pbox[17]做首次输入(相当于上面的全0的输入),用类似的方法,替换key_sbox 信息加密。信息加密就是用函数把待加密信息x分成32位的两部分:xL,xR BF_En对输入信息进行变换,BF_En函数详细过程如下:

对于i=1至16
xL=xL^Pi
xR=F(xL)^xR
交换xL和xR(最后一轮取消该运算)
xR=xR^P17
xL=xL^P18
重新合并xL和xR
函数F见下图:

8位 32位
|-----------S盒1-----------
| |加
| 8位 32位 |----
|-----------S盒2----------- |
| |
| |异或----
32位-| | |
| 8位 32位 | |
|-----------S盒3--------------- |加
| |-----------------32位
| |
| |
| 8位 32位 |
|-----------S盒4-----------------------

把xL分成4个8位分组:a,b,c和d
输出为:F(xL)=((((S[1,a]+S[2,b])MOD 4294967296)^s[3,c])+S[4,d])MOD 4294967296
(2的32次方) (2的32次方)
重新合并后输出的结果就是我们需要的密文。
用BlowFish算法解密,同样也需要两个过程。
1.密钥预处理
2.信息解密
密钥预处理的过程与加密时完全相同
信息解密的过程就是把信息加密过程的key_pbox逆序使用即可。

可以看出,选择不同的key,用BlowFish算法加密同样的信息,可以得出不同的结果。
要破解BlowFish算法,就是要得到BlowFish算法的key。所以,使用BlowFish算法进行加密,最重要的也就是key的选择以及key的保密。其中key的选择可以使用bf_sdk中的_WeakKey函数进行检验。以下是该函数的说明:

源文:
---------------------------------------------------------------------------------------
_WeakKey
Function : Test if the generated Boxes are weak
Argument : none
Return : AX = Status (1=weak, 0=good)
Affects : AX, BX, CX, DX, SI, DI, direction Flag
Description: After "_InitCrypt" you should test the Boxes with this function.
If they provide a weakness which a cryptoanalyst could use to
break the cipher a "1" is returned. In this case you should
reload the original boxes and let the user choose a different
password.
---------------------------------------------------------------------------------------
译文:
---------------------------------------------------------------------------------------
_WeakKey
功能:测试产生的box是否安全
参数:无
返回:AX=1 不安全;AX=0 安全
影响:AX, BX, CX, DX, SI, DI, 方向标志
描述:使用"_InitCrypt"函数产生用于加密的Boxes后,你应该用这个函数测试产生的Boxes是否安全。如果该key产生的Boxes不安全——可以被密码分析者通过分析Boxes得到key,那么,你应该采用另外一个key产生一个安全的Boxes用来加密。

---------------------------------------------------------------------------------------

二、BlowFish's CrackMe1分析

由于该CrackMe主要是测试你的密码学知识,所以没有在其他方面设关卡。为了减小文件体积,缩短大家下载的时间,用upx加了壳,直接用Trw2000的"PNewSec+Makepe"很方便地就能脱掉壳。
用常规的方法,很快找到下面关键比较处:
:004015D9 51 push ecx
:004015DA 52 push edx
:004015DB 6880894000 push 00408980
:004015E0 E8EBFAFFFF call 004010D0 //BF_De(sn)
:004015E5 8B442464 mov eax, dword ptr [esp+64]
:004015E9 , 8B0DF0994000 mov ecx, dword ptr [004099F0]
:004015EF 83C41C add esp, 0000001C
:004015F2 3BC1 cmp eax, ecx //比较
:004015F4 7529 jne 0040161F
:004015F6 8B4C244C mov ecx, dword ptr [esp+4C]
:004015FA A1EC994000 mov eax, dword ptr [004099EC]
:004015FF 3BC8 cmp ecx, eax //比较
:00401601 751C jne 0040161F
:00401603 6A30 push 00000030
由于BlowFish算法加密,解密输出的信息都是64Bit的,所以要进行两次比较。
我们既然知道了他对我们的sn进行的变换是BF_De,那么,很显然,我们要找到程序初始化key_pbox和key_sbox的地方。跟进4015E0的Call,找到key_pbox在408980处,下bpm,然后跟踪,分析,找到程序初始化key_pbox和key_sbox的地方,如下:

:004016C0 50 push eax

* Possible StringData Ref from Data Obj ->"CrackingForFun"
|
:004016C1 6844804000 push 00408044
:004016C6 6880894000 push 00408980
:004016CB E860FAFFFF call 00401130 //初始化Boxes
由此我们知道了BF_De(sn)的key是"CrackingForFun"。
问题的一半已经解决了。下面我们来看用来比较的另外的64Bit的数是从何而来。
bpm 4099EC w
跟踪分析后,发现这个用来比较的数是由BF_En(ComputerID,key="ChinaCrackingGroup")生成。
至此,我们可以写出注册机的算法
sn=BF_En((BF_En(ComputerID,key="ChinaCrackingGroup"),key="CrackingForFun")
只要你编程够强,密码学也还过得去,写出这个东西的注册机就不是困难的事情了。
附:
ComputerID的产生
如果你对这个CrackMe很有兴趣,还想研究一下他的ComputerID是如何产生的,也可以继续跟踪,分析,在这里,我给处我分析的结果:
ComputerID=BF_En(0776f6c62h, 068736966h,key=PW_1)
其中,PW_1就是你的Windows版本号,可以在“系统属性”里头看到,也就是注册表中的
H_L_M/Software/Microsoft/Windows/CurrentVersion 中的ProductId项。在我的机器上是:
"25001-O

你可能感兴趣的:(算法和数据结构,算法,加密,c,cryptography,algorithm,解密)