C语言RSA大数运算库,[转载]RSA大数运算库 c++实现
转自http://blog.chinaunix.net/u1/50055/showart_1686985.html
基于以下原因,俺估计RSA算法会被越来越多的共享软件采用:
1、原理简洁易懂
2、加密强度高
3、专利限制已过期
4、看雪老大三番五次呼吁共享软件采用成熟的非对称加密技术
所以,大家应该对RSA算法进行深入了解。
RSA依赖大数运算,目前主流RSA算法都建立在512位到1024位的
大数运算之上,所以我们在现阶段首先需要掌握1024位的大数
运算原理。
大多数的编译器只能支持到64位的整数运算,即我们在运算中
所使用的整数必须小于等于64位,即:0xffffffffffffffff
也就是18446744073709551615,这远远达不到RSA的需要,于是
需要专门建立大数运算库来解决这一问题。
最简单的办法是将大数当作字符串进行处理,也就是将大数用
10进制字符数组进行表示,然后模拟人们手工进行“竖式计算”
的过程编写其加减乘除函数。但是这样做效率很低,因为1024
位的大数其10进制数字个数就有数百个,对于任何一种运算,
都需要在两个有数百个元素的数组空间上做多重循环,还需要
许多额外的空间存放计算的进位退位标志及中间结果。当然其
优点是算法符合人们的日常习惯,易于理解。
另一种思路是将大数当作一个二进制流进行处理,使用各种移
位和逻辑操作来进行加减乘除运算,但是这样做代码设计非常
复杂,可读性很低,难以理解也难以调试。
于是俺琢磨了一种介于两者之间的思路:
将大数看作一个n进制数组,对于目前的32位系统而言n可以取
值为2的32次方,即0x10000000,假如将一个1024位的大数转
化成0x10000000进制,它就变成了32位,而每一位的取值范围
就不是0-1或0-9,而是0-0xffffffff。我们正好可以用一个无
符号长整数来表示这一数值。所以1024位的大数就是一个有32
个元素的unsigned long数组。而且0x100000000进制的数组排列
与2进制流对于计算机来说,实际上是一回事,但是我们完全
可以针对unsigned long数组进行“竖式计算”,而循环规模
被降低到了32次之内,并且算法很容易理解。
例如大数18446744073709551615,等于“ffffffff ffffffff”,
它就相当于10进制的“99”:有两位,每位都是ffffffff。
而大数18446744073709551616,等于“00000001 00000000
00000000”,它就相当于10进制的“100”:有三位,第一位是
1,其它两位是0。如果我们要计算18446744073709551616
-18446744073709551615,就类似于100-99:
00000001 00000000 00000000
- ffffffff ffffffff
-----------------------------
= 0 0 1
所以,可以声明大数类如下:
//大数运算库头文件:BigInt.h
//作者:afanty@vip.sina.com
//版本:1.0 (2003.4.26)
//说明:适用于MFC
#define BI_MAXLEN
40
#define DEC 10
#define HEX 16
class CBigInt
{
public:
int m_nSign;
//记录大数的符号,支持负值运算
int m_nLength;
//记录0x10000000进制的位数,0-40之间,相当于2进制的0-1280位
unsigned long
m_ulvalue[BI_MAXLEN]; //记录每一位的“数字”
CBigInt();
~CBigInt();
//将大数赋值为另一个大数 CBigInt&
Mov(CBigInt& A);
//将大数赋值为编译器能够理解的任何整形常数或变量 CBigInt&
Mov(unsigned __int64 A);
//比较两个大数大小
int
Cmp(CBigInt& A);
//计算两个大数的和
CBigInt
Add(CBigInt& A);
//重载函数以支持大数与普通整数相加
CBigInt Add(long
A);
//计算两个大数的差
CBigInt
Sub(CBigInt& A);
//重载函数以支持大数与普通整数相减
CBigInt Sub(long
A);
//计算两个大数的积
CBigInt
Mul(CBigInt& A);
//重载函数以支持大数与普通整数相乘
CBigInt Mul(long
A);
//计算两个大数的商
CBigInt
Div(CBigInt& A);
//重载函数以支持大数与普通整数相除
CBigInt Div(long
A);
//计算两个大数相除的余数
CBigInt
Mod(CBigInt& A);
//重载函数以支持大数与普通整数相除求模
long Mod(long
A);
//将输入的10进制或16进制字符串转换成大数
int
InPutFromStr(CString& str, const unsigned int
system);
//将大数按10进制或16进制格式输出到字符串
int
OutPutToStr(CString& str, const unsigned int
system);
//欧几里德算法求:Y=X.Euc(A),使满足:YX mod A = 1
CBigInt
Euc(CBigInt& A);
//蒙哥马利算法求:Y=X.Mon(A,B),使满足:X^A mod B = Y
CBigInt
Mon(CBigInt& A, CBigInt& B);
};
注意以上函数的声明格式,完全遵循普通整数运算的习惯,例如大数
Y=X+Z 相当于 Y.Mov(X.(Add(Z)),这样似乎没有Mov(Y,Add(X,Z))
看起来舒服,但是一旦我们重载运算符“=”为“Mov”,“+”为“Add”,
则Y.Mov(X.(Add(Z))的形式就等价于 Y=X+Z。
俺不知道其他编程语言里是否支持运算浮重载,至少这样定义函数格式
在C++里可以带来很大的方便。
下面让我们来实现大数类的主要成员函数:
//大数运算库源文件:BigInt.cpp
//作者:afanty@vip.sina.com
//版本:1.0 (2003.4.26)
//说明:适用于MFC
#include
"stdafx.h"
#include "BigInt.h"
//初始化大数为0
CBigInt::CBigInt()
{
m_nSign=1;
m_nLength=1;
for(int i=0;i
}
//采用缺省的解构函数
CBigInt::~CBigInt()
{
}
//大数比较,如果大数A位数比大数B多,当然A>B
//如果位数相同,则从高位开始比较,直到分出大小
int CBigInt::Cmp(CBigInt& A)
{
if(m_nLength>A.m_nLength)return 1;
if(m_nLength
for(int i=m_nLength-1;i>=0;i--)
{
if(m_ulvalue[i]>A.m_ulvalue[i])return 1;
if(m_ulvalue[i]
}
return 0;
}
//照搬参数的各属性
CBigInt& CBigInt::Mov(CBigInt&
A)
{
m_nLength=A.m_nLength;
for(int
i=0;i
return *this;
}
//大数相加
//调用形式:N.Add(A),返回值:N+A
//若两大数符号相同,其值相加,否则改变参数符号再调用大数相减函数
例如:
A
B C
+ D
E
--------------
= S F G
H
其中,若C+E<=0xffffffff,则H=C+E,carry(进位标志)=0
若C+E>0xffffffff,则H=C+E-0x100000000,carry=1
若B+D+carry<=0xfffffff,则G=B+D,carry=0
若B+D+carry>0xfffffff,则G=B+D+carry-0x10000000,carry=1
若carry=0,则F=A,S=0
若carry=1,A<0xfffffff,则F=A+1,S=0
若carry=1,A=0xfffffff,则F=0,S=1
CBigInt CBigInt::Add(CBigInt& A)
{
CBigInt X;
if(X.m_nSign==A.m_nSign)
{
X.Mov(*this);
int carry=0;
unsigned __int64 sum=0;
if(X.m_nLength
for(int i=0;i
{
sum=A.m_ulvalue[i];
sum=sum+X.m_ulvalue[i]+carry;
X.m_ulvalue[i]=(unsigned long)sum;
if(sum>0xffffffff)carry=1;
else carry=0;
}
if(X.m_nLength
{
X.m_ulvalue[X.m_nLength]=carry;
X.m_nLength+=carry;
}
return X;
}
else{X.Mov(A);X.m_nSign=1-X.m_nSign;return Sub(X);}
}
//大数相减
//调用形式:N.Sub(A),返回值:N-A
//若两大数符号相同,其值相减,否则改变参数符号再调用大数相加函数
例如:
A
B C
- D
E
--------------
= F G
H
其中,若C>=E,则H=C-E,carry(借位标志)=0
若C
若B-carry>=D,则G=B-carry-D,carry=0
若B-carry
若carry=0,则F=A
若carry=1,A>1,则F=A-1
若carry=1,A=1,则F=0
CBigInt CBigInt::Sub(CBigInt& A)
{
CBigInt X;
if(m_nSign==A.m_nSign)
{
X.Mov(*this);
int cmp=X.Cmp(A);
if(cmp==0){X.Mov(0);return X;}
int len,carry=0;
unsigned __int64 num;
unsigned long *s,*d;
if(cmp>0)
{
s=X.m_ulvalue;
d=A.m_ulvalue;
len=X.m_nLength;
}
if(cmp<0)
{
s=A.m_ulvalue;
d=X.m_ulvalue;
len=A.m_nLength;
X.m_nSign=1-X.m_nSign;
}
for(int i=0;i
{
if((s[i]-carry)>=d[i])
{
X.m_ulvalue[i]=s[i]-carry-d[i];
carry=0;
}
else
{
num=0x100000000+s[i];
X.m_ulvalue[i]=(unsigned long)(num-carry-d[i]);
carry=1;
}
}
while(X.m_ulvalue[len-1]==0)len--;
X.m_nLength=len;
return X;
}
else{X.Mov(A);X.m_nSign=1-X.m_nSign;return Add(X);}
}
//大数相乘
//调用形式:N.Mul(A),返回值:N*A
例如:
A B C
* D E
----------------
= S F
G H
+ T I J
K
----------------
= U V L M
N
其中,SFGH=ABC*E,TIJK=ABC*D
而对于:
A
B C
* E
-------------
= S F G H
其中,若C*E<=0xffffffff,则H=C*E,carry(进位标志)=0
若C*E>0xffffffff,则H=(C*E)&0xffffffff
carry=(C*E)/0xffffffff
若B*E+carry<=0xffffffff,则G=B*E+carry,carry=0
若B*E+carry>0xffffffff,则G=(B*E+carry)&0xffffffff
carry=(B*E+carry)/0xffffffff
若A*E+carry<=0xffffffff,则F=A*E+carry,carry=0
若A*E+carry>0xffffffff,则F=(A*E+carry)&0xffffffff
carry=(A*E+carry)/0xffffffff
S=carry
CBigInt CBigInt::Mul(CBigInt& A)
{
CBigInt X,Y;
unsigned __int64 mul;
unsigned long carry;
for(int
i=0;i
{
Y.m_nLength=m_nLength;
carry=0;
for(int j=0;j
{
mul=m_ulvalue[j];
mul=mul*A.m_ulvalue[i]+carry;
Y.m_ulvalue[j]=(unsigned long)mul;
carry=(unsigned long)(mul>>32);
}
if(carry&&(Y.m_nLength
{
Y.m_nLength++;
Y.m_ulvalue[Y.m_nLength-1]=carry;
}
if(Y.m_nLength
{
Y.m_nLength+=i;
for(int
k=Y.m_nLength-1;k>=i;k--)Y.m_ulvalue[k]=Y.m_ulvalue[k-i];
for(k=0;k
}
X.Mov(X.Add(Y));
}
if(m_nSign+A.m_nSign==1)X.m_nSign=0;
else X.m_nSign=1;
return X;
}
//大数相除
//调用形式:N.Div(A),返回值:N/A
//除法的关键在于“试商”,然后就变成了乘法和减法
//这里将被除数与除数的试商转化成了被除数最高位与除数最高位的试商
CBigInt CBigInt::Div(CBigInt& A)
{
CBigInt X,Y,Z;
int len;
unsigned __int64 num,div;
unsigned long carry=0;
Y.Mov(*this);
while(Y.Cmp(A)>0)
{ if(Y.m_ulvalue[Y.m_nLength-1]>A.m_ulvalue[A.m_nLength-1])
{
len=Y.m_nLength-A.m_nLength;
div=Y.m_ulvalue[Y.m_nLength-1]/(A.m_ulvalue[A.m_nLength-1]+1);
}
else if(Y.m_nLength>A.m_nLength)
{
len=Y.m_nLength-A.m_nLength-1;
num=Y.m_ulvalue[Y.m_nLength-1];
num=(num<<32)+Y.m_ulvalue[Y.m_nLength-2];
if(A.m_ulvalue[A.m_nLength-1]==0xffffffff)div=(num>>32);
else div=num/(A.m_ulvalue[A.m_nLength-1]+1);
}
else
{
X.Mov(X.Add(1));
break;
}
Z.Mov(div);
Z.m_nLength+=len;
for(int
i=Z.m_nLength-1;i>=len;i--)Z.m_ulvalue[i]=Z.m_ulvalue[i-len];
for(i=0;i
X.Mov(X.Add(Z));
Z.Mov(Z.Mul(A));
Y.Mov(Y.Sub(Z));
}
if(Y.Cmp(A)==0)X.Mov(X.Add(1));
if(m_nSign+A.m_nSign==1)X.m_nSign=0;
else X.m_nSign=1;
return X;
}
//大数求模
//调用形式:N.Mod(A),返回值:N%A
//求模与求商原理相同
CBigInt CBigInt::Mod(CBigInt& A)
{
CBigInt X,Y;
int len;
unsigned __int64 num,div;
unsigned long carry=0;
X.Mov(*this);
while(X.Cmp(A)>0)
{ if(X.m_ulvalue[X.m_nLength-1]>A.m_ulvalue[A.m_nLength-1])
{
len=X.m_nLength-A.m_nLength;
div=X.m_ulvalue[X.m_nLength-1]/(A.m_ulvalue[A.m_nLength-1]+1);
}
else if(X.m_nLength>A.m_nLength)
{
len=X.m_nLength-A.m_nLength-1;
num=X.m_ulvalue[X.m_nLength-1];
num=(num<<32)+X.m_ulvalue[X.m_nLength-2];
if(A.m_ulvalue[A.m_nLength-1]==0xffffffff)div=(num>>32);
else div=num/(A.m_ulvalue[A.m_nLength-1]+1);
}
else
{
X.Mov(X.Sub(A));
break;
}
Y.Mov(div);
Y.Mov(Y.Mul(A));
Y.m_nLength+=len;
for(int
i=Y.m_nLength-1;i>=len;i--)Y.m_ulvalue[i]=Y.m_ulvalue[i-len];
for(i=0;i
X.Mov(X.Sub(Y));
}
if(X.Cmp(A)==0)X.Mov(0);
return X;
}
//暂时只给出了十进制字符串的转化
int CBigInt::InPutFromStr(CString& str, const
unsigned int system=DEC)
{
int len=str.GetLength();
Mov(0);
for(int i=0;i
{
Mov(Mul(system));
int k=str[i]-48;
Mov(Add(k));
}
return 0;
}
//暂时只给出了十进制字符串的转化
int CBigInt::OutPutToStr(CString& str, const
unsigned int system=DEC)
{
str="";
char ch;
CBigInt X;
X.Mov(*this);
while(X.m_ulvalue[X.m_nLength-1]>0)
{
ch=X.Mod(system)+48;
str.Insert(0,ch);
X.Mov(X.Div(system));
}
return 0;
}
//欧几里德算法求:Y=X.Euc(A),使满足:YX mod A=1
//相当于对不定方程ax-by=1求最小整数解
//实际上就是初中学过的辗转相除法
例如:11x-49y=1,求x
11 x -
49 y = 1
a)
49=5 -> 11 x -
5 y = 1
b)
11%5 =1 -> x
- 5 y =
1 c)
令y=1
代入c)式 得x=6
令x=6 代入b)式 得y=13
令y=13 代入a)式 得x=58 CBigInt CBigInt::Euc(CBigInt& A)
{
CBigInt X,Y;
X.Mov(*this);
Y.Mov(A);
if((X.m_nLength==1)&&(X.m_ulvalue[0]==1))return
X;
if((Y.m_nLength==1)&&(Y.m_ulvalue[0]==1)){X.Mov(X.Sub(1));return
X;}
if(X.Cmp(Y)==1)X.Mov(X.Mod(Y));
else Y.Mov(Y.Mod(X));
X.Mov(X.Euc(Y));
Y.Mov(*this);
if(Y.Cmp(A)==1)
{
X.Mov(X.Mul(Y));
X.Mov(X.Sub(1));
X.Mov(X.Div(A));
}
else
{
X.Mov(X.Mul(A));
X.Mov(X.Add(1));
X.Mov(X.Div(Y));
}
return X;
}
//蒙哥马利算法求:Y=X.Mon(A,B),使满足:X^A mod B=Y
//俺估计就是高中学过的反复平方法
CBigInt CBigInt::Mon(CBigInt& A,
CBigInt& B)
{
CBigInt X,Y,Z;
X.Mov(1);
Y.Mov(*this);
Z.Mov(A);
while((Z.m_nLength!=1)||Z.m_ulvalue[0])
{
if(Z.m_ulvalue[0]&1)
{
Z.Mov(Z.Sub(1));
X.Mov(X.Mul(Y));
X.Mov(X.Mod(B));
}
else
{
Z.Mov(Z.Div(2));
Y.Mov(Y.Mul(Y));
Y.Mov(Y.Mod(B));
}
}
return X;
}
C语言RSA大数运算库,[转载]RSA大数运算库 c++实现相关推荐
- MacOS下使用C语言基于openssl库进行RSA加密解密
MacOS下使用C语言基于openssl库进行RSA加密解密 1 安装openssl并生成密钥 首先当然要安装openssl(这里记得看一下安装路径,应该是/usr/local/Cellar/open ...
- python rsa库_python RSA加密解密
RSA加密(pip install pycryptodome) 总结: Pycrypto提供了比较完善的加密算法.RSA广泛用于加密与解密,还有数字签名通信领域.使用Publick/Private秘钥 ...
- 配置 不使用rsa 密码_了解使用RSA的密码学
配置 不使用rsa 密码 RSA is an asymmetric cryptographic algorithm that you are probably using right now to v ...
- 非对称加密算法之RSA介绍及OpenSSL中RSA常用函数使用举例
RSA算法,在1977年由Ron Rivest.Adi Shamirh和LenAdleman,在美国的麻省理工学院开发完成.这个算法的名字,来源于三位开发者的名字.RSA已经成为公钥数据加密标准. R ...
- 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)
相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...
- python实现rsa加密源代码_python实现RSA加密(解密)算法
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准. 今天只有短的RSA钥匙才可能被强力方式解破.到2008年为止,世界上还没有任何可靠 ...
- 基于java的rsa加密程序_RSA rsa加密程序,rsa java源码和 rsa的jsp Crypt_De algrithms 解密 238万源代码下载- www.pudn.com...
文件名称: RSA下载 收藏√ [ 5 4 3 2 1 ] 开发工具: Java 文件大小: 169 KB 上传时间: 2014-04-23 下载次数: 0 提 供 者: 姚双奇 详细说明: ...
- python常用第三方库(转载)
Python标准库与第三方库详解(转载) 转载地址: http://www.codeweblog.com/python%e6%a0%87%e5%87%86%e5%ba%93%e4%b8%8e%e7%a ...
- [GO语言基础] 四.算术运算、逻辑运算、赋值运算、位运算及编程练习
作为网络安全初学者,会遇到采用Go语言开发的恶意样本.因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识:另一方面是分享与读者,希望大家一起进步.前文介绍了Golang的 ...
- PKCS#1 v2.1 RSA Cryptography Standard (PKCS#1 RSA密码学规范,版本2.1)
PKCS#1 v2.1: RSA密码学规范 RSA实验室 2002年6月14日 --翻译:CaesarZou (zoudeqiang1979@tsinghua.org.cn) 1.介绍 这个文档提供了 ...
最新文章
- Dorado用法与示例
- html 内部浮动外部不,CSS:外部层高度自适应内部浮动层高度的方法
- Android Fragment 简单实例
- JavaScript函数补完:toString()
- URL访问 和命名规范
- 图形学opengl实验二-桌子的矩阵变换
- 晚上没有路灯,我骑的很慢
- JavaScript var语句简析
- bzoj 1552: [Cerc2007]robotic sort bzoj 3506: [Cqoi2014]排序机械臂(splay区间翻转)
- JDBC批处理插入更新MySQL Oracle
- hdu 5335 Walk Out(bfs+斜行递推) 2015 Multi-University Training Contest 4
- ps投影怎么做之教程:人像投影和物体长投影制作
- 解决office的PPT和WPS的PPT不兼容的问题
- GreenPlum系列-5-角色和权限
- Oracle数据库字段翻译
- c#程序设计实训报告心得体会_C#程序实际实训总结
- 2022年全球市场硬化疗法总体规模、主要企业、主要地区、产品和应用细分研究报告
- 交易所要变天?去中心化交易所崛起,蚕食用户,抢夺流量
- Oracle 11g 数据库 实验7 数据库安全管理
- 你真的了解整流桥的结构和原理吗?
热门文章
- 六大场景,看懂声纹识别技术怎样“抗疫防疫” 小快
- BusHound详细使用说明
- soundpool android,Android中用SoundPool播放音频
- java经典错误语句_【Java】Java代码经典错误清单
- MOS管耗尽型和增强型的区别是什么呢?
- 删除远程桌面登录的记录(mstsc)
- 短视频无水印解析源码
- 使用css实现产品分类,DIV+CSS实现京东商城分类适合所有版本
- t分布 u分布 卡方分布_卡方分布、t分布和f分布各有哪些重要性质?
- VHDL学习:两种方式实现四选一选择器