【www.guakaob.com--结构师考试】
篇一:《蒙哥马利算法》
蒙哥马利算法
俺曾经查阅了网上找得到的各种用于实现RSA 的大数运算库,然而最终还是决
定自己动手写一个。因为凡是效率高速度快的代码(crypto++、miracl、freelip、
rsaref等),要么使用的数据结构过于复杂,要么编码风格杂乱无章,俺的水平和 耐心都实在是有限,以至于无法读懂这些东西。而俺读得懂的一些代码,其实现方 式却又过于幼稚,效率极低速度一塌糊涂。俺觉得像俺这样的人不在少数,于是决 心写一个清晰易懂,效率也过得去的东西奉献给大家。
这个函数库刚做好的时候,生成1024位的随机密钥耗时大约5 分钟,俺认为是
可以接受的。但后来找到一个叫tE! 的老外用miracl库写的RsaTools,发现其生成 1024位的密钥耗时不超过三秒钟!于是俺针对俺的代码开始了艰苦的优化工作,希 望能达到甚至超过这一水平。一周之后1024位密钥的平均生成时间已经降至5 秒左 右,但是单单依靠优化代码来进一步提高速度也非常困难了。于是俺开始借助金山 词霸来查阅能够通过google找到的一切与RSA 算法相关的论文,但是网上关于RSA 算法的论述绝大多数都是用于硬件实现的,将其算法流程用软件设计语言来实现极 其繁琐。而且俺发现这样做下去俺只会离自己的初衷越来越远:俺的代码将不再清 晰易懂。所以俺一度准备放弃。
准备放弃之后,心态平静了许多,再回头去看那些原来不太能够理解的RSA 算
法原理,却发现其实也不是那么高深莫测,不急不躁地慢慢看,慢慢想,突然就一 下子全明白了。一番改进之后,现在这个版本的函数库同样具有非常简单而清晰的 结构,速度也不算慢,生成1024位的密钥在俺PIII 900的笔记本上平均耗时不超过 两秒。程序使用C++ 编写,可在VC6.0 下直接编译通过,希望大家喜欢。如果发现 Bug 或者有好的修改建议,俺将非常感谢您能够给俺一个Mail。
最后,感谢看雪论坛,感谢雪兄多次热心相助,俺在此学到了很多知识,当然
还要乘机拍拍马屁,感谢俺家甜甜的支持!
afanty@vip.sina.com
原理介绍
RSA 原理:
选取两个不同的大素数p、q,并计算N=p*q
选取小素数d,并计算e,使d*e % (p-1)(q-1)=1
对于任意A<N:
若B=A**d % N
则A=B**e % N
可见d、e形成了非对称秘钥关系,加密者用公钥d加密,解密者可用私钥e解密,第 三者即使拦截了密文B、公钥d和N,在不知道p、q的前提下,无法推算出e,从而无 法获得明文A。当N取非常大的值时,将其因式分解成p、q是非常困难的,例如当N 为1024 bit时,据分析,需动用价值数千万美金的大型计算机系统并耗费一年的时 间。
RSA 密钥的选取和加解密过程都非常简洁,在算法上主要要实现四个问题:
1、如何处理大数运算
2、如何求解同余方程 XY % M = 1
3、如何快速进行模幂运算
4、如何获取大素数
实际上,在实现RSA 算法的过程中大家会发现后三个问题不是各自独立的,它们互 有关联,环环相套,相信届时你会意识到:RSA算法是一种“优美”的算法!
大数存储
RSA 依赖大数运算,目前主流RSA 算法都建立在1024位的大数运算之上。而大 多数的编译器只能支持到64位的整数运算,即我们在运算中所使用的整数必须小于 等于64位,即:0xffffffffffffffff,也就是18446744073709551615,这远远达不
到RSA 的需要,于是需要专门建立大数运算库来解决这一问题。
最简单的办法是将大数当作数组进行处理,数组的各元素也就是大数每一位上
的数字,通常采用最容易理解的十进制数字0—9。然后对“数字数组”编写加减乘
除函数。但是这样做效率很低,因为二进制为1024位的大数在十进制下也有三百多 位,对于任何一种运算,都需要在两个有数百个元素的数组空间上多次重循环,还 需要许多额外的空间存放计算的进退位标志及中间结果。另外,对于某些特殊的运 算而言,采用二进制会使计算过程大大简化,而这种大数表示方法转化成二进制显 然非常麻烦,所以在某些实例中则干脆采用了二进制数组的方法来记录大数,当然 这样效率就更低了。
一个有效的改进方法是将大数表示为一个n 进制数组,对于目前的32位系统而
言n 可以取值为2 的32次方,即 0x100000000,假如将一个二进制为1024位的大数 转化成0x10000000进制,就变成了32位,而每一位的取值范围不再是二进制的0—1 或十进制的0—9,而是0-0xffffffff,我们正好可以用一个32位的DWORD (如:无 符号长整数,unsigned long) 类型来表示该值。所以1024位的大数就变成一个含
有32个元素的 DWORD数组,而针对 DWORD数组进行各种运算所需的循环规模至多32
次而已。而且0x100000000 进制与二进制,对于计算机来说,几乎是一回事,转换 非常容易。
例如大数18446744073709551615,等于 0xffffffff ffffffff,就相当于十进
制的99:有两位,每位都是0xffffffff。而18446744073709551616等于0x00000001 00000000 00000000,就相当于十进制的100:有三位,第一位是1 ,其它两位都是 0 ,如此等等。在实际应用中,“数字数组”的排列顺序采用低位在前高位在后的
方式,这样,大数A 就可以方便地用数学表达式来表示其值:
A=Sum[i=0 to n](A*r**i),r=0x100000000,0<=A<r
其中Sum 表示求和,A表示用以记录A 的数组的第i 个元素,**表示乘方。
任何整数运算最终都能分解成数字与数字之间的运算,在0x100000000 进制下
其“数字”最大达到0xffffffff,其数字与数字之间的运算,结果也必然超出了目
前32位系统的字长。在VC++中,存在一个__int64 类型可以处理64位的整数,所以 不用担心这一问题,而在其它编译系统中如果不存在64位整形,就需要采用更小的
进制方式来存储大数,例如16位的WORD类型可以用来表示0x10000 进制。但效率更 高的办法还是采用32位的 DWORD类型,只不过将0x100000000 进制改成0x40000000 进制,这样两个数字进行四则运算的最大结果为 0x3fffffff * 0x3fffffff,小于
0xffffffffffffff,可以用一个双精度浮点类型(double,52位有效数字)来储存
这一中间结果,只是不能简单地用高位低位来将中间结果拆分成两个“数字”。
加减乘除
设有大数A、B和C,其中A>=B:
A=Sum[i=0 to p](A*r**i)
B=Sum[i=0 to q](B*r**i)
C=Sum[i=0 to n](C*r**i)
r=0x100000000,0<=A,B,C<r,p>=q
则当C=A+B、C=A-B、C=A*B时,我们都可以通过计算出C来获得C:
C=A+B,显然C不总是等于A+B,因为A+B可能>0xffffffff,而C
必须<=0xffffffff,这时就需要进位,当然在计算C[i-1]时也可能产生了进位,所
以计算C时还要加上上次的进位值。如果用一个64位变量result来记录和,另一 个32位变量carry来记录进位,则有:
carry=0
FOR i FROM 0 TO p
result=A+B+carry
C=result%0x100000000蒙哥马利的名言怎么理解。
carry=result/0x100000000
IF carry=0 n=p
ELSE n=p+1
C=A-B,同理C不总是等于A-B,因为A-B可能<0,而C必须>=0,
这时就需要借位,同样在计算C[i-1]时也可能产生了借位,所以计算C时还要减 去上次的借位值:
carry=0
FOR i FROM 0 TO p
IF A-B-carry>=0
C=A-B-carry
carry=0
ELSE
C=0x100000000+A-B-carry
carry=1
n=p
WHILE C[n]=0 n=n-1
C=A*B,首先我们需要观察日常做乘法所用的“竖式计算”过程:
A3 A2 A1 A0
* B2 B1 B0
-------------------------------
= A3B0 A2B0 A1B0 A0B0
+ A3B1 A2B1 A1B1 A0B1蒙哥马利的名言怎么理解。
+ A3B2 A2B2 A1B2 A0B2
-------------------------------
= C5 C4 C3 C2 C1 C0
可以归纳出:C=Sum[j=0 to q](A[i-j]*B[j]),其中i-j必须>=0且<=p。当然这
一结论没有考虑进位,虽然计算A[i-j]*B[j]和Sum的时候都可能发生进位,但显然 这两种原因产生的进位可以累加成一个进位值。最终可用如下算法完成乘法: n=p+q-1
carry=0蒙哥马利的名言怎么理解。
For i FROM 0 TO n
result=carry
For j FROM 0 TO q
IF 0<=i-j<=p result=result+A[i-j]*B[j]
C=result%0x100000000
carry=result/0x100000000
IF carry!=0
n=n+1
C[n]=carry
对于C=A/B,由于无法将B 对A“试商”,我们只能转换成B[q]对A[p]的试商来得到 一个近似值,所以无法直接通过计算C来获得C,只能一步步逼近C。由于: B*(A[p]/B[q]-1)*0x100000000**(p-q)<C
令:X=0,重复A=A-X*B,X=X+(A[p]/B[q]-1)*0x100000000**(p-q),直到A<B 则:X=A/B,且此时的A=A%B
注意对于任意大数A*0x100000000**k,都等价于将A 的数组中的各元素左移k 位, 不必计算;同样,A/0x100000000**k则等价于右移。
欧几里得方程
在RSA 算法中,往往要在已知A、N的情况下,求 B,使得 (A*B)%N=1。即相当 于求解B、M都是未知数的二元一次不定方程 A*B-N*M=1 的最小整数解。
而针对不定方程ax-by=c 的最小整数解,古今中外都进行过详尽的研究,西方 有著名的欧几里德算法,即辗转相除法,中国有秦九韶的“大衍求一术”。事实上
二元一次不定方程有整数解的充要条件是c为a、b的最大公约数。即当c=1时,a、b 必须互质。而在RSA算法里由于公钥d为素数,素数与任何正整数互质,所以可以通 过欧几里德方程来求解私钥e。
欧几里德算法是一种递归算法,比较容易理解:
例如:11x-49y=1,求x
(a) 11 x - 49 y = 1 49%11=5 ->
(b) 11 x - 5 y = 1 11%5 =1 ->
(c) x - 5 y = 1
令y=0 代入(c)得x=1
篇二:《蒙哥马利算法》
自己曾经查阅了网上找得到的各种用于实现RSA 的大数运算库,然而最终还是决 定自己动手写一个。因为凡是效率高速度快的代码(crypto++、miracl、freelip、 rsaref等),要么使用的数据结构过于复杂,要么编码风格杂乱无章,自己的水平和 耐心都实在是有限,以至于无法读懂这些东西。而俺读得懂的一些代码,其实现方 式却又过于幼稚,效率极低速度一塌糊涂。俺觉得像俺这样的人不在少数,于是决 心写一个清晰易懂,效率也过得去的东西奉献给大家。
这个函数库刚做好的时候,生成1024位的随机密钥耗时大约5 分钟,俺认为是 可以接受的。但后来找到一个叫tE! 的老外用miracl库写的RsaTools,发现其生成 1024位的密钥耗时不超过三秒钟!于是俺针对俺的代码开始了艰苦的优化工作,希 望能达到甚至超过这一水平。一周之后1024位密钥的平均生成时间已经降至5 秒左 右,但是单单依靠优化代码来进一步提高速度也非常困难了。于是俺开始借助金山 词霸来查阅能够通过google找到的一切与RSA 算法相关的论文,但是网上关于RSA 算法的论述大多数都是用于硬件实现的,将其算法流程用软件设计语言来实现极 其繁琐。而且俺发现这样做下去俺只会离自己的初衷越来越远:俺的代码将不再清 晰易懂。所以俺一度准备放弃。
准备放弃之后,心态平静了许多,再回头去看那些原来不太能够理解的RSA 算 法原理,却发现其实也不是那么高深莫测,不急不躁地慢慢看,慢慢想,突然就一 下子全明白了。一番改进之后,现在这个版本的函数库同样具有非常简单而清晰的 结构,速度也不算慢,生成1024位的密钥在俺PIII 900的笔记本上平均耗时不超过 两秒。程序使用C++ 编写,可在VC6.0 下直接编译通过,希望大家喜欢。如果发现 Bug 或者有好的修改建议,俺将非常感谢您能够给俺一个Mail。
最后,感谢看雪论坛,感谢雪兄多次热心相助,俺在此学到了很多知识,当然
还要乘机拍拍马屁,感谢俺家甜甜的支持!
afanty@vip.sina.com
原理介绍
RSA 原理:
选取两个不同的大素数p、q,并计算N=p*q
选取小素数d,并计算e,使d*e % (p-1)(q-1)=1
对于任意A<N:
若B=A**d % N
则A=B**e % N
可见d、e形成了非对称秘钥关系,加密者用公钥d加密,解密者可用私钥e解密,第 三者即使拦截了密文B、公钥d和N,在不知道p、q的前提下,无法推算出e,从而无 法获得明文A。当N取非常大的值时,将其因式分解成p、q是非常困难的,例如当N 为1024 bit时,据分析,需动用价值数千万美金的大型计算机系统并耗费一年的时 间。
RSA 密钥的选取和加解密过程都非常简洁,在算法上主要要实现四个问题:
1、如何处理大数运算
2、如何求解同余方程 XY % M = 1
3、如何快速进行模幂运算
4、如何获取大素数
实际上,在实现RSA 算法的过程中大家会发现后三个问题不是各自独立的,它们互 有关联,环环相套,相信届时你会意识到:RSA算法是一种“优美”的算法!
大数存储
RSA 依赖大数运算,目前主流RSA 算法都建立在1024位的大数运算之上。而大 多数的编译器只能支持到64位的整数运算,即我们在运算中所使用的整数必须小于 等于64位,即:0xffffffffffffffff,也就是18446744073709551615,这远远达不
到RSA 的需要,于是需要专门建立大数运算库来解决这一问题。
最简单的办法是将大数当作数组进行处理,数组的各元素也就是大数每一位上
的数字,通常采用最容易理解的十进制数字0—9。然后对“数字数组”编写加减乘 除函数。但是这样做效率很低,因为二进制为1024位的大数在十进制下也有三百多 位,对于任何一种运算,都需要在两个有数百个元素的数组空间上多次重循环,还 需要许多额外的空间存放计算的进退位标志及中间结果。另外,对于某些特殊的运 算而言,采用二进制会使计算过程大大简化,而这种大数表示方法转化成二进制显 然非常麻烦,所以在某些实例中则干脆采用了二进制数组的方法来记录大数,当然 这样效率就更低了。
一个有效的改进方法是将大数表示为一个n 进制数组,对于目前的32位系统而
言n 可以取值为2 的32次方,即 0x100000000,假如将一个二进制为1024位的大数 转化成0x10000000进制,就变成了32位,而每一位的取值范围不再是二进制的0—1 或十进制的0—9,而是0-0xffffffff,我们正好可以用一个32位的DWORD (如:无 符号长整数,unsigned long) 类型来表示该值。所以1024位的大数就变成一个含
有32个元素的 DWORD数组,而针对 DWORD数组进行各种运算所需的循环规模至多32 次而已。而且0x100000000 进制与二进制,对于计算机来说,几乎是一回事,转换 非常容易。
例如大数18446744073709551615,等于 0xffffffff ffffffff,就相当于十进
制的99:有两位,每位都是0xffffffff。而18446744073709551616等于0x00000001 00000000 00000000,就相当于十进制的100:有三位,第一位是1 ,其它两位都是
0 ,如此等等。在实际应用中,“数字数组”的排列顺序采用低位在前高位在后的 方式,这样,大数A 就可以方便地用数学表达式来表示其值:
A=Sum[i=0 to n](A*r**i),r=0x100000000,0<=A<r
其中Sum 表示求和,A表示用以记录A 的数组的第i 个元素,**表示乘方。 任何整数运算最终都能分解成数字与数字之间的运算,在0x100000000 进制下 其“数字”最大达到0xffffffff,其数字与数字之间的运算,结果也必然超出了目
前32位系统的字长。在VC++中,存在一个__int64 类型可以处理64位的整数,所以 不用担心这一问题,而在其它编译系统中如果不存在64位整形,就需要采用更小的 进制方式来存储大数,例如16位的WORD类型可以用来表示0x10000 进制。但效率更 高的办法还是采用32位的 DWORD类型,只不过将0x100000000 进制改成0x40000000 进制,这样两个数字进行四则运算的最大结果为 0x3fffffff * 0x3fffffff,小于
0xffffffffffffff,可以用一个双精度浮点类型(double,52位有效数字)来储存 这一中间结果,只是不能简单地用高位低位来将中间结果拆分成两个“数字”。 加减乘除
设有大数A、B和C,其中A>=B:
A=Sum[i=0 to p](A*r**i)
B=Sum[i=0 to q](B*r**i)
C=Sum[i=0 to n](C*r**i)
r=0x100000000,0<=A,B,C<r,p>=q
则当C=A+B、C=A-B、C=A*B时,我们都可以通过计算出C来获得C:
C=A+B,显然C不总是等于A+B,因为A+B可能>0xffffffff,而C蒙哥马利的名言怎么理解。
必须<=0xffffffff,这时就需要进位,当然在计算C[i-1]时也可能产生了进位,所 以计算C时还要加上上次的进位值。如果用一个64位变量result来记录和,另一 个32位变量carry来记录进位,则有:
carry=0
FOR i FROM 0 TO p
result=A+B+carry
C=result%0x100000000
carry=result/0x100000000
IF carry=0 n=p
ELSE n=p+1
C=A-B,同理C不总是等于A-B,因为A-B可能<0,而C必须>=0,
这时就需要借位,同样在计算C[i-1]时也可能产生了借位,所以计算C时还要减 去上次的借位值:
carry=0
FOR i FROM 0 TO p
IF A-B-carry>=0
C=A-B-carry
carry=0
ELSE
C=0x100000000+A-B-carry
carry=1
n=p
WHILE C[n]=0 n=n-1
篇三:《《蒙哥马利:强者就是不断挑战自己》备课参考》
《蒙哥马利:强者就是不断挑战自己》备课参考(人教版高二选修备课资
料)(jiaoan1.7139.com)
此内容来自:
教学提示
这篇传记作为课外阅读,主要供学生在课下阅读、思考,老师可提示给学生阅读的重点,但不必占用上课时间。限于篇幅,在学生课本中没有选收课文,只列出篇目、阅读提示和思考题。建议有兴趣的同学找来原文阅读。蒙哥马利的传记很多,教科书中介绍的是比较简易的一种。有兴趣的同学,可以找一些更为详尽的军事家传记来读。现今中学生特别是男生中不少人对军事感兴趣,应当适当满足他们这种要求;而且选读一些军旅生活的传记,对于培养学生的意志力和为事业献身的精神,也会有帮助。 《蒙哥马利》虽然是一篇人物小传,但在勾勒传主英雄业绩时,牵涉到许多关于第二次世界大战的历史知识,读起来可能有些障碍。教师可以提供有关二战历史的简要材料,帮助学生排除阅读“障碍”。其实,布置阅读时,应当指明本课要点,让学生把注意力放到了解蒙哥马利军旅生涯中那些英雄的表现上,感受何谓“军人本色”,何谓“永不言败”。引导学生理解,这种永不服输的坚毅精神,不止是对军人和战争显得可贵,对所有希望能够干一番事业的人来说,都是需要的。
思考与探究
第一题主要引导学生从传记传奇性的军旅生活描写中,理解优秀的军人和军事家的素质。可以让学生各抒己见。
第二题提到教材中有好几篇传记都写到传主青少年时期个性很强,不受家庭和学校“规矩”的约束,并不是“好学生”。蒙哥马利这篇传记开头也写到他的“顽劣”,但他们终究又都成为非常出色的人。关键要引导学生分析理解这些“顽劣”或者“不守规矩”中蕴涵的独立思考、主动性、创造性等可贵的性格趋向,这就不再是通常所说的性格缺陷,加上能够找到自己的兴趣点,建立自己健全的人生方向,并为了这个方向顽强奋斗,这些突出的个性就有可能成为事业与人生成功的动力。
第三题训练小传的写作。建议启发学生抓住人物性格特征的某一个突出方面,勾勒出人物的形象。
追忆
梦幻网络()——教育资源第一站
来源:梦幻网络()
2013年02月09日
点击查看完整内容:
更多 语文综合文摘 请查看:
更多 语文教案 请查看:
篇四:《关于写作的名人名言》
1、文学是一种奢侈;虚构则是一种必需。——切斯特顿
2、写作要严格、严格、再严格。求快这意味着不是往上爬,而是从上坡向下滚,到头来只有死路一条。——富曼诺夫
3、文章合为时而著,诗歌合为事而作。关于写作的名人名言。——白居易
4、天才的作品是用眼泪灌溉的。——巴尔扎克
5、故事可以虚构,细节不能捏造。——佚名
6、一个作家必须使他的艺术给人以自然的印象,而不是矫揉造作。自然是有说服力的,而矫揉则适得其反。——亚里士多德
7、文采是一枝魔杖,它可以点石成金。——史密斯
8、灵感,这是一个不喜欢采访懒汉的客人。——车尔尼雪夫斯基
9、给人深刻印象的叙述,乃是文风第一位的东西。关于写作的名人名言。——萧伯纳
10、写文章和写戏都最怕冗长的独白。——丁玲
11、我们常把自己的写作冲动误认为自己的写作才能,自以为要写就意味着会写。——钱钟书
12、笔乃心灵之舌。——塞万提斯
13、最难的是幵头,也就是第一句。就像在音乐中一样,第一句可以给整篇作品定一个调子,通常要费很长时间去寻找它。——高尔基
14、文学创作的技巧,首先在于研究语言,
本文来源:http://www.guakaob.com/jianzhugongchengkaoshi/343054.html