是不是觉得不可思议?椭圆曲线,怎么变成了这般模样,成了一个一个离散的点? 椭圆曲线在不同的数域中会呈现出不同的样子,但其本质仍是一条椭圆曲线。举一个不太恰当的例子,好比是水,在常温下,是液体;到了零下,水就变成冰,成了固体;而温度上升到一百度,水又变成了水蒸气。但其本质仍是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算法演 变而来。 -------------------------------------------------------------------------------- yutian 回复于:2004-04-12 10:02:59 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采用比特长的密钥,其他实体使用比特的密钥。 -------------------------------------------------------------------------------- yutian 回复于:2004-04-12 10:03:42 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算法却作不到。 -------------------------------------------------------------------------------- yutian 回复于:2004-04-12 10:06:05 一、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算法在应用上的误区,留下了被人攻击、被人破译的极大隐患。 -------------------------------------------------------------------------------- yutian 回复于:2004-04-12 10:08:19 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算法却作不到。 -------------------------------------------------------------------------------- yutian 回复于:2004-04-12 10:09:40 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.近似优化了每一轮中的循环左移位移量以实现更快的雪崩效应.各轮的位移量互不相同. -------------------------------------------------------------------------------- yutian 回复于:2004-04-12 10:11:12 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 |