大整数算法[00] 概述

★ 为啥要做这个

早在大一的时候,我便对密码学产生兴趣。那时在计算机导论后面看到RSA加密的计算原理,觉得十分有趣,于是就很想自己实现一个RSA加密,不过我很快就放弃了,因为实在搞不定那超长的整数计算。C里面最长的整数类型也就64位,对于动辄就1024位的RSA密钥,这连个零头都没有。为了完成这个目标,我便开始琢磨着弄一个用来计算大整数的库。原本我也打算使用别人已经写好的大数库,不过最终还是决定自己搞一个,因为凡是效率高速度快的大数库 (OpenSSL, Crypto++, GMP),要么使用的数据结构很复杂,要么编码风格比较奇葩,对于刚学编程的我来说水平和耐心都实在是有限,以至于无法完全读懂这些东西,有一些我能看明白的代码,其实现方式又比较幼稚,效率很低速度慢得一塌糊涂,最后想想,自己做一个的话不仅能弄明白大整数计算是如何实现的,而且也顺带提升一下自己的编码能力,何乐而不为呢?

★ 用途

做一个项目,清晰的定位还是十分有必要的,不然容易偏离自己的初衷。对于这个大整数库,我的定位就是用于密码学(准确的说是公钥密码学),只做整数的计算,不做浮点数计算(那是给科学计算用的,加密完全用不上)

★ 要求

虽然大整数算法的计算开销比其他算法的开销要大,但是通过精心的优化,大部分开销还是可以保持在较小的水平。对于我自己做的这个库,只要能接近OpenSSL的效率,我就满足了,但是代码尽量做到简洁易懂,不要像OpenSSL或者GMP那样太复杂。编程使用C语言,对于一些关键的地方,考虑使用内联汇编进行优化。

★ 本系列博文的内容

本系列博文,主要是介绍大整数算法的实现,分享一些编程心得,顺带讲讲算法背后的一点点理论。

★ 参考的资料

Handbook of Applied Cryptography ( HAC )

BigNum Math-Implementing Cryptographic Multiple Precision Arithmetic

OpenSSL

PolarSSL

LibTomMath

★ 结尾

这个大整数库在2014年年初便开始动工,花了有大半年的时间来做,目前已经完工了,虽然跟其他的库比起来可能还有一些不足,但是我花在这上面的心血还是很大的,所以决定写点博文来分享一些自己的心得。

为了方便阅读,把本系列博文的目录整理如下

01. 大整数的表示和相关定义

02. 基本的操作(维护算法)

03. 比较操作

04. 位设置操作

05. 移位操作

06. 绝对值加法

07. 绝对值减法

08. 有符号加法和减法

09. Comba乘法

10. Karatsuba乘法

11. 有符号乘法

12. Comba平方

13. Karatsuba平方

14. 有符号平方

15. 带余数除法

未完待续........

时间: 2024-10-14 12:25:00

大整数算法[00] 概述的相关文章

大整数算法[01] 大整数的表示和相关定义

★ 相关的数据类型定义 在干正事之前,先定义好各种数据类型还是很有必要的,避免在以后的编码中引起混乱. uintX   X位无符号整形,如uint32表示32位无符号整形 intX    X位有符号整形,如int32表示32位有符号整形 基本数据类型定义: #ifdef _MSC_VER            typedef __int8              int8;            typedef __int16             int16;            typ

大整数算法[08] Comba乘法(原理)

★ 引子          原本打算一篇文章讲完,后来发现篇幅会很大,所以拆成两部分,先讲原理,再讲实现.实现的话相对复杂,要用到内联汇编,要考虑不同平台等等. 在大整数计算中,乘法是非常重要的,因为在公钥密码学中模幂运算要频繁使用乘法,所以乘法的性能会直接影响到模幂运算的效率.下面将会介绍两种乘法:基线乘法和 Comba 乘法,尽管他们的原理和计算看起来十分类似,而且算法的时间复杂度都是 O(n^2),但是他们的效率差别是很大的. ★ 基线乘法 (Baseline Multiplication

大整数算法[11] Karatsuba乘法

★ 引子         前面两篇介绍了 Comba 乘法,最后提到当输入的规模很大时,所需的计算时间会急剧增长,因为 Comba 乘法的时间复杂度仍然是 O(n^2).想要打破乘法中 O(n^2) 的限制,需要从一个完全不同的角度来看待乘法.在下面的乘法算法中,需要使用 x 和 y 这两个大整数的多项式基表达式 f(x) 和 g(x) 来表示. 令 f(x) = a * x + b,g(x) = c * x + d,h(x) = f(x) * g(x).这里的 x 相当于一个基,比如十进制下,

大整数算法[13] 单数位乘法

★ 引子 最近在折腾 wxWidgets,同时拖延症又犯了,所以中断了好久.这次来讲讲单数位乘法,前面讲到 Comba 和 Karatsuba 乘法,这两个算法适合用来处理比较大的整数,但是对于一个大整数和一个单精度数相乘,其效果反而会不好,因为计算量过多.实际上单数位乘法只是基线乘法的一个特例,不存在嵌套循环进位,因此可以通过优化减少计算量.另外与完整的乘法不同的是,单数位乘法不需要什么临时变量存储和内存分配(目标精度增加除外). ★ 算法思路         单数位乘法类似于计算 12345

大整数算法

本文主要整理了几个常用的大整数的算法:大整数加法大整数乘法大整数阶乘大整数幂其实大体的思路都差不多,都是用数组来存储大整数.以下的代码仅仅实现功能,并没有充分详细的参数判断,在实际运用中,肯定是需要考虑的. 大整数相加 1 #include <stdio.h> 2 #include <string.h> 3 #define N 1000 4 void get_num(int *array) 5 { 6 char str[N] = {'\0'}; 7 int loop = 0; 8

大整数算法[04] 位操作

上一篇文章介绍了大整数的比较操作,今天来谈谈和位相关的操作. ★ 引子         在大整数的表示和相关定义这篇文章中讲到了大整数是如何表示的.为了方便后面的讲解,这里先按照前面的定义,给出一个大整数的例子(32位系统下,每一个数位长度为32比特): 假设有一 bignum x,十进制值为 1134924633606254832,对应的十六进制值为 0xFC00FF0F0F0F0F0,那么按照大整数的表示方法, 2^32 进制就表示成(每一位用逗号隔开): (264245232,404232

大整数算法[08] 有符号加法和减法

★ 引子 前面几篇文章介绍了比较操作,绝对值加法和绝对值减法,现在就可以利用这几个算法构建有符号数的加减算法. ★ 有符号数加法            有符号数的加法分成两种情况:同号和异号. 1.  如果两个数同号,则执行绝对值加法,如果两个数为非负数,则结果为非负数:如果两个数都是负数,则结果也为负数. 2.  如果两个数异号,则要执行绝对值减法,用绝对值较大的数去减绝对值较小的数.最终结果 z 的符号由 x 和 y 的绝对值大小决定:如果 x 的绝对值大于或等于 y,则 z 的符号与 x

大整数算法[02] 基本的操作(维护算法)

上一篇博文简单介绍了大整数的表示方法,这次开始介绍一些基本的算法.       ★ 初始化和清除 编写大整数函数的出发点是bignum结构的初始化和清除,在其他大部分算法当中,这两个算法都会用到. 对于给定的bignum结构,初始化有两种情况:一是仅仅把bignum结构的dp指向NULL,二是初始化的时候顺便分配一定的动态内存,并让dp指针指向这块内存.其实我本来打算只用第二种方式进行初始化,不过考虑到初始内存可能分配过多导致内存浪费,于是决定两种方式一起使用.第一种方式的优点是在后面编程中你不

[转]大整数算法[11] Karatsuba乘法

★ 引子         前面两篇介绍了 Comba 乘法,最后提到当输入的规模很大时,所需的计算时间会急剧增长,因为 Comba 乘法的时间复杂度仍然是 O(n^2).想要打破乘法中 O(n^2) 的限制,需要从一个完全不同的角度来看待乘法.在下面的乘法算法中,需要使用 x 和 y 这两个大整数的多项式基表达式 f(x) 和 g(x) 来表示. 令 f(x) = a * x + b,g(x) = c * x + d,h(x) = f(x) * g(x).这里的 x 相当于一个基,比如十进制下,