RSA编码实现(复杂版)

  • (一) 题目
  • (二)分析
  • (三)整体代码
  • (四)运行结果
  • (五)不足之处

(一) 题目

(二)分析

关于随机选取16bit的素数
16bit的十进制数范围为[0—65535] ,[20,216-1],将这个范围内所有素数(大致6000+个)求出来放在数组中,通过随机选取数组元素的编号,实现随机选取p,q
关于数据类型
16bit的p,q产生的n的位数必然在32bit范围内,而对于过程中的一些辅助变量(比如高次方幂运算是会大于32bit的)
下面是各种数据类型的字节、位数、有无符号:

数据类型 位数 字节数 有无符号 数范围
unsigned short (int) 16位 2 [0,216-1]
int 32位 4 [-231,231-1]
unsigned (int) 32位 4 [0,232-1]
unsigned long long 64位 8 [0,264-1]

所以:全局大部分变量用的是无符号的32位 unsigned int
部分变量使用64位 unsigned long long

(三)整体代码


#include<iostream>
#include<iomanip>
using namespace std;#define Prime_Count 6541  // [3, 65535]内的所有素数,总共有6541个素数,这6541个素数随机选取两个作为P,Q
#define BinarySize 40          // 部分数组的大小 这里只是因为40>32//判断素数       Eratosthenes筛法:正整数n是素数,当且仅当它不能被任何一个小于sqrt(n)的素数整除
unsigned   IsPrime(unsigned n)
{unsigned   temp = (unsigned  )sqrt(n);for (unsigned  i = 2; i <= temp; i++){if (n % i == 0) return 0;//n不是素数的话返回0}return 1;//n是素数的话返回1
}//计算16bit的所有素数,即范围在[3, 65535]内的所有素数,总共有6541个素数,并赋值到数组Prime[]中 .        这里不考虑2,因为计算欧拉函数后相当于只是一个素数的欧拉函数(2-1)*(Q-1)void All_Prime_Number(unsigned  Prime[])
{unsigned  j = 0;for (unsigned  i = 3; i < 65535; i = i + 2)//i+2跳过偶数(加快循环)         {       if (IsPrime(i) == 1){Prime[j] = i;           j++;}}
}//在Prime[Prime_Count]中,随机挑选两个不相同的素数p,q
void RandomChoose_Prime_Number(unsigned &p, unsigned &q, unsigned Prime[])
{srand((unsigned)time(NULL));//确保随机性unsigned Choose_P =(unsigned)rand() % (Prime_Count );//在从[0,6540]共6541个数里面随机选一个  //cout << "Choose_P=" << Choose_P << endl;//Plus_Q表示在P的数组标号上的增量,为了P,Q不相等(即数组下标不相等),增量的范围是[1,6540]unsigned  Plus_Q = (unsigned)rand() % (Prime_Count - 1)+1;//增量的范围是[1,6540]//cout << "Plus_Q=" << Plus_Q << endl;unsigned  Choose_Q = (Choose_P + Plus_Q) % (Prime_Count );// % Prime_Count 是因为Choose_P + Plus_Q可能会超过6541//cout << "Choose_Q=" << Choose_Q << endl;p = Prime[Choose_P];q = Prime[Choose_Q];cout << "   Bob选取的两素数为:p=" << p << "," << "q=" << q << endl;
}//计算n和n的欧拉函数值
void N(unsigned p, unsigned  q, unsigned  &n, unsigned &Euler_n)
{n =p *q;Euler_n = (p-1) * (q-1);cout << "   Bob计算出的公钥为:{ e=5,n=" << n << "}"<<endl;
}//求逆元d  扩展欧几里得算法(递归版)  y是中间负责传递值的变量
void Eucild_D(unsigned e, unsigned  Euler_n, unsigned long long& d, unsigned long long& y)  // d 是 e mod Euler_n 的乘法逆元{if (0 == Euler_n){d = 1, y = 0;return;}Eucild_D(Euler_n, e % Euler_n, d, y);unsigned long long flag = d;d = y;y = flag - e / Euler_n * y;}
/*
//这是一开始的求逆元算法,一个数一个数的试,数字小还能算出来,数字大的时候时间超慢超长
void Euild_D(unsigned   e, unsigned   Euler_n, unsigned  & d)
{unsigned  Sign_of_Inverse_Element = 0;//判断是否求出逆元的标志:Sign_of_Inverse_Element。当Sign_of_Inverse_Element=1,则求出了逆元do{for (unsigned  i = Euler_n/e; i < Euler_n; i++){unsigned long pro=((unsigned long)i * (unsigned long)e) % Euler_n;if (pro == 1){Sign_of_Inverse_Element = 1; //Sign_of_Inverse_Element=1时表面求出了逆元dd = i;}}} while (Sign_of_Inverse_Element != 1);cout <<"d="<< d << endl;
}
*///将明文串的ASCII值('abc'=(int)6382179)转为比特串,然后根据n的大小来对比特串分组,将分割后的数放入m_partition[BinarySize]中;
//Partition_count比特串分组组数            m_partition_bits比特串分组每组的位数           m_partition[]存放比特串分组的数组
void WholeASCII_to_WholeInt_to_WholeBinary_to_PartitionBinary_to_PartitionInt(unsigned  n, unsigned  &Partition_count, unsigned  & m_partition_bits ,unsigned  m_partition[])
{//ASCIIunsigned m;m = (unsigned )'abc';cout <<"   Alice想要发送的明文为"<< "abc"<<endl;cout <<"   明文abc的ASCII值为" << m<< endl;//ASCII转比特串unsigned   Positive_Binary[BinarySize] = { 0 };  //正序存放二进制数0和1,二进制的小端放在数组的小序号unsigned   Reverse_Binary[BinarySize] = { 0 };  //倒序存放二进制数0和1,二进制的大端放在数组的小序号(这个是真正的二进制表示)因为十进制整数转二进制,先逐步模二取余,然后倒序排列unsigned  remainder;//余数unsigned  index=0;//计数量while (m != 0){remainder = m % 2;  //m除以2的余数m= m / 2;  //m被2整除的商Positive_Binary[index] = remainder;  //将余数存放在数组Positive_Binary[BinarySize]中,这里是正序排放,index++;}cout << "   明文abc转为比特串后的比特串位数为:" << index <<"位"<< endl;//倒序比特串for (unsigned long i = 0; i < index; i++){Reverse_Binary[i] = Positive_Binary[index-i-1];//求倒叙排列}cout << "   总的明文比特串为:";for (unsigned i = 0; i < index; i++){cout << Reverse_Binary[i] << setw(1);}cout << endl;m_partition_bits = (unsigned  )(log(n) / log(2));//对m的二进制截取的位数m_partition_bits<=[log2(n)]向下取整cout <<"   比特串分割后每组的位数为:"<< m_partition_bits <<"位"<< endl;unsigned  Sign_of_Round_up;//向上取整的标志 if (index % m_partition_bits != 0) {Sign_of_Round_up = 1;}else{ Sign_of_Round_up = 0; }//cout << "Sign_of_Round_up=" << Sign_of_Round_up << endl;Partition_count = (unsigned)(index / m_partition_bits) + Sign_of_Round_up;//m根据截取的位数m_partition_bits被划分成m_Partition_count个部分cout << "   共有" << Partition_count << "个比特串分割小组"<<endl ;//将每个比特串分组(二进制)都转成十进制  (for 循环表达)//下面注释里还有while表达(似乎while没成功)for (unsigned  i = 0 ; i < Partition_count; i++){unsigned  Sign;//比特串分组的尾部元素的取值if (index-1 <=(i + 1) * m_partition_bits - 1 ){Sign = index - 1;}else{Sign = (i + 1) * m_partition_bits - 1; }unsigned   Sum=0;for (unsigned  j = i* m_partition_bits; j <= Sign; j++){//求2的( j % m_partition_bits)次方unsigned  pow=1;for (unsigned k = 0; k < j % m_partition_bits; k++){pow = pow * 2;}Sum = Sum + Positive_Binary[j]*pow;// 这里用的是Positive_Binary[](小端对小端),所以是j(且用Positive_Binary[]明显要比 Reverse_Binary[BinarySize] 便于计算)}m_partition[i] =(unsigned )Sum;cout << "   第" << i +1<< "个明文分割小组的值为" << m_partition[i] << endl;}/*unsigned  ZLS=0;while (ZLS < Partition_count){cout << "ZLS=" << ZLS << endl;unsigned  Sign;if (index - 1 <= (ZLS + 1) * m_partition_bits - 1){Sign = index - 1;}else{Sign = (ZLS + 1) * m_partition_bits - 1;}cout << "Sign=" << Sign << endl;unsigned   Sum = 0;for (unsigned j =ZLS * m_partition_bits; j <= Sign; j++){unsigned  pow = 1;for (unsigned  k = 0; k < j % m_partition_bits; k++){pow = pow * 2;}cout << "pow = " << pow << endl;Sum = Sum + Positive_Binary[j] * pow;// 这里用的是Positive_Binary[](小端对小端),所以是j(且用Positive_Binary[]明显要比 Reverse_Binary[BinarySize] 便于计算)}m_partition[ZLS] = (unsigned )Sum;cout << "m_partition[" << ZLS << "]=" << m_partition[ZLS] << endl;ZLS = ZLS + 1;}*/
}//对于明文m_partition[BinarySize]的加密,得到c_partition[BinarySize]
void E_M(unsigned  m_partition[], unsigned  Partition_count, unsigned  e, unsigned  n, unsigned  c_partition[])
{for (unsigned  i = 0; i < Partition_count; i++){unsigned long long product = 1;//product表示m_partition[i]自身不断相乘的积  for (unsigned  j = 1; j <= e ; j++)//用e来控制m_partition[i]的指数{product = (product * m_partition[i]) % n;//注意不要忘记%n  }c_partition[i] = (unsigned  )product;cout << "   第" << i +1<< "个明文分割小组加密后的值为" << c_partition[i] << endl;}//cout << endl;
}//把c_partition[BinarySize] 以二进制的形式在信道传播 //对密文c_partition[BinarySize]的解密,得到After_m_partition[BinarySize]
void D_C(unsigned  c_partition[], unsigned  Partition_count, unsigned d, unsigned n, unsigned After_m_partition[])
{unsigned long long N = (unsigned long long)n;for (unsigned  i = 0; i < Partition_count; i++){unsigned long long product = 1;//product表示c_partition[BinarySize]自身不断相乘的积for (unsigned long long  j = 1; j <= d; j++)//用d来控制c_partition[BinarySize]的指数{            product = (  product * (unsigned long long)c_partition[i])   % N;//注意不要忘记%n}After_m_partition[i] = (unsigned)product;cerr << "   第" << i +1<< "个密文分割小组解密后的值为" << After_m_partition[i] << endl;}
}//将分割的After_m_partition[BinarySize]合并成大整数,然后转为字符串C
void PartitionInt_to_WholeInt_to_WholeASCII(unsigned   After_m_partition[], unsigned m_partition_bits,unsigned   Partition_count,char str[])
{unsigned Sum_After_m_partition_bits=0;unsigned  C_Sum=0;for (unsigned  i = 0; i < Partition_count; i++){unsigned  pow = 1;for (unsigned k = 0; k < Sum_After_m_partition_bits; k++){pow = pow * 2;}//cout << "pow=" << pow << endl;C_Sum = C_Sum + pow* After_m_partition[i];//cout << "C_Sum=" << C_Sum << endl;Sum_After_m_partition_bits = Sum_After_m_partition_bits+ m_partition_bits;}//如何把str[]直接转成char C?str[0] = (char)(C_Sum & 0xff);str[1] = (char)((C_Sum >> 8) & 0xff);str[2] = (char)((C_Sum >> 16) & 0xff);str[3] = (char)((C_Sum >> 24) & 0xff);cout << "   Bob解密后得到的明文为:" << str[2] << str[1] << str[0] << endl;}int main()
{unsigned  Prime[Prime_Count];unsigned  p , q ;unsigned  n, Euler_n;unsigned   e = 5;unsigned  long long d,y;unsigned  Partition_count;unsigned   m_partition_bits;unsigned   m_partition[BinarySize];unsigned   c_partition[BinarySize];unsigned  After_m_partition[BinarySize];cout << "《Bob想要收到来自他人的信息,于是Bob开始制作公私密钥》" << endl;cout << "{"<<endl;//求所有素数,并随机选取两素数All_Prime_Number(Prime);RandomChoose_Prime_Number(p, q, Prime);//计算n,和n的欧拉函数N(p, q,n, Euler_n);//计算逆元dEucild_D( e,  Euler_n,  d,y);cout << "   Bob计算出的秘密钥:{ d=" << d << ",n="<<n<<"}"<<endl;cout << "}" << endl;cout << endl<<endl;cout << "《Bob将计算出来的公钥广播发给所有人:"<<"“ 我是Bob,想要给我发消息,就用这个公钥:{ e=5,n=" << n << "}”》"<< endl<<endl<<endl;cout << "《Alice想要给Bob发送明文,于是Alice开始对明文加密》" << endl;cout << "{" << endl;//对明文分割并加密明文WholeASCII_to_WholeInt_to_WholeBinary_to_PartitionBinary_to_PartitionInt( n, Partition_count, m_partition_bits, m_partition);E_M(m_partition, Partition_count, e, n, c_partition);cout << "}" << endl;cout <<endl<<endl;//Alice将密文通过信道发送给Bobcout << "《Alice将密文通过信道发送给Bob》"<<endl<<endl<<endl;cout << "《Bob收到密文后开始解密》"<<endl;cout << "{" << endl;//解密密文D_C(c_partition, Partition_count, d, n, After_m_partition);char str[4];PartitionInt_to_WholeInt_to_WholeASCII(After_m_partition, m_partition_bits,Partition_count, str);cout << "}" << endl;cout << endl << endl<<endl;system("pause");return 0;
}

(四)运行结果

成功的



失败的

(五)不足之处

1.欧几里得求逆元的函数是从别处找的代码,还没研究具体流程和原理是什么。但是已经发现有时候d会被赋值为1,造成解码出错
2.当d大于15亿,运算时间超长,算不出来结果。

RSA加密算法(32bit比特级运算)(复杂版)(C++实现)相关推荐

  1. [转帖]在SQL SERVER中实现RSA加密算法

    /*本次修改增加了unicode的支持,但是加密后依然显示为16进制数据,因为进行RSA加密后所得到的unicode编码是无法显示的,所以密文依然采用16进制数据显示. 需要特别注意:如果要对中文进行 ...

  2. 用实例给新手讲解RSA加密算法

    用实例给新手讲解RSA加密算法 2009年06月24日14:04 来源: 我有话说 查看评论(2) 好文我顶(3) 图为 RSA公开密钥算法的发明人,从左到右Ron Rivest, Adi Shami ...

  3. RSA加密算法原理和java简单实现

    数学 RSA加密算法中,用到素数.互质数.指数运算.模运算等几个数学知识. 素数 素数又称质数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数. 互质数 百度百科:公因数只有 ...

  4. RSA加密算法——密码学笔记(四)

    一.数学知识 1. 质数 质数,又称素数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数. 2. 互质数 百度百科上的解释是:公因数只有1的两个数,叫做互质数. 维基百科上的 ...

  5. 密码学:RSA加密算法详解

    概述 本文旨在说明RSA加密算法的原理及实现,而其相关的数学部分的证明则不是本文内容. 版权说明 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:Q-WHai 发表日期: ...

  6. RSA加密算法原理及RES签名算法简介(转载)

    第一部分:RSA算法原理与加密解密 一.RSA加密过程简述 A和B进行加密通信时,B首先要生成一对密钥.一个是公钥,给A,B自己持有私钥.A使用B的公钥加密要加密发送的内容,然后B在通过自己的私钥解密 ...

  7. rsa加密c语言源码库,RSA加密算法源代码C语言实现.doc-资源下载在线文库www.lddoc.cn...

    RSA加密算法_源代码__C语言实现.doc RSA 算法 1978 年就出现了这种算法,它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作,也很流行.算法的名字以发明者的名字命名Ro ...

  8. 快速了解什么是RSA加密算法

    1.什么是RSA 加密算法有对称加密和非对称加密. 对称加密是指发送方和接收方使用相同的一种规则对信息进行处理,因为双方使用的是相同的规则和密钥,所以一旦密钥泄露,那么再强大的加密也将毫无用处. 所有 ...

  9. RSA加密算法加密与解密过程解析

    1.加密算法概述 加密算法根据内容是否可以还原分为可逆加密和非可逆加密. 可逆加密根据其加密解密是否使用的同一个密钥而可以分为对称加密和非对称加密. 所谓对称加密即是指在加密和解密时使用的是同一个密钥 ...

最新文章

  1. 电脑任务管理器_电脑任务管理器没有进程怎么办
  2. 谷歌发布史上最强人类大脑「地图」,在线可视3D神经元「森林」!
  3. http方式调用第三方接口
  4. CodeAnyWhere
  5. 转 abap中sy-index和sy-tabix使用的时候有什么区别
  6. android平板 深度学习,这款叫Remix的设备,或许可以拯救安卓平板
  7. 为什么 c = tf.matmul(a, b) 不立即执行矩阵乘法?
  8. Spring @Async配置4. 基于@Async无返回值调用 使用的方式非常简单,一个标注即可解决所有的问题: 1 @Async //标注使用 2 public void asyncMe
  9. 生命游戏 并行化_新加坡电音制作人楚晴Jasmine《困兽游戏》,讲述爱情间的博弈...
  10. 计算机课教案学法,计算机应用基础教学方法初探
  11. 国内手机厂商AR布局报告
  12. SpringBoot在前端发送url时,不能识别特殊字符的问题
  13. wifislax14.0final reaver穷举PIN教程 wap,wps破解教程
  14. VelocityTracker
  15. Egret引擎基础教程I(下载安装创建第一个项目)
  16. Ubuntu 12.04无法识别华为U8500
  17. 【TK精灵】一款界面友好的桌面程序(exe)进程守护管理软件
  18. 怎么保存python文件_pycharm怎么保存py文件
  19. 如何快速画好一张程序流程图
  20. D3D管线以及着色器工作原理-画一个三角形

热门文章

  1. scrapy爬取表情包使用flask搭建搜索网站
  2. 如何让用html制作404页面,网站404页面怎么做?
  3. vscode源代码管理不显示修改的文件夹
  4. 小提琴统计图_箱形图和小提琴图
  5. 微信小程序中wxml中用data-id传出的数据在js中的获取方法。
  6. 邀你来看 | CSDN公开课 利用容器技术打造AI公司技术中台
  7. 大球分析系统_走地大球分析系统app
  8. 电脑上怎么登录几个微信(微信多开)?不需要安装软件的方法,超简单
  9. 微光系列之青春无敌美少女
  10. HCIP-DATACOM H12-831(41-60)