HNU物联网安全第一次实验

任务

通过编程实现 RSA 算法,理解非对称密码算法和公钥密码体制的基本原理,掌握 RSA 算法的计算过程和安全性约束。本实验要求自己编程实现加密算法,调用编译环境内置加密函数视为无效。 要求:
1、利用 c++ 实现 RSA 算法,要求使用面向对象的方法,分别实现文件的加密和解密方法。
2、加密方法格式为:void encrypt(string file,string destFile,string key) {...},
解密方法格式为:void decode(string file,string destFile,string key) {...},
密钥生成方法格式为:string genKey(int length){...}。
3、参数说明:file 待加密(解密)的文件路径,destFile 加密(解密) 后文件的存放路径,Key 密钥 ,length 密钥长度。

汇报

 

 主要来说就是,RSA是一种非对称加密算法,用公钥加密,私钥解密。

我们先来看下rsa算法的数学基础。

Rsa算法的安全性是基于大整数质因数分解这个问题的,整数越大分解难度越高。

第二个是miller-rabin素数测试,它是基于费马小定理的概率性素数测试算法,用于rsa算法中素数生成时的检测。

第三个是模幂运算,它是rsa加解密过程的基础,通常用模重复平方法来实现。

现在介绍一下rsa算法的原理。

发送者想将消息m发送给接收者,首先要进行加密。加密就需要密钥。密钥生成方法如左下角所示。首先找到两个很大的素数pq,然后求它们的乘积n,以及n的欧拉函数值φ(n) 。然后随机找一个小于φ(n)且与φ(n)互质的指数e,并求出e在模φ(n) 下的逆元d

其中,en是公钥,dn是私钥。公钥和私钥是由接收者生成的,他将公钥公开,私钥只有自己知道。

发送者想发消息给接收者时,他首先用公钥en,对明文消息m进行c = m^e mod n这个运算得到密文c。然后将密文c通过公共信道传给接收者。

接收者收到想解密时,将dn作为私钥,对密文c进行m = c^d mod n这个运算,返回明文m

 

首先看一下密钥生成函数。它接收一个参数length表示密钥长度。

开头有个密钥长度检查确保密钥不会太短。

然后生成长度为length/2的两个随机的大素数pq

这个大素数生成函数的代码是怎么样的呢?首先初始化随机数生成器,并算出指定bits位的数的最大值和最小值。

在循环中,每次生成64位随机数,而bits 可能远超 64,所以将多个64位块拼接成一个 bits 位的数。

然后,通过取模的方式,确保num[min, max] 范围内。此外还要确保num是奇数。

然后判断num是不是素数,如果是就返回num,不是就继续循环重新生成。

这个判断一个数是否是素数的方法就是Miller-Rabin质数测试。n是要判断的数,另一个参数是要进行多少轮验证。

它的原理是费马小定理和二次探测定理,这是信安数学的有关知识,有兴趣的同学可以自己去了解一下。

首先将一个n-1表示为d × 2^s

 然后在2n-2之间随机选择一个计数a,计算a^d mod n的结果存入x,如果x==1x==n-1则本轮验证通过,进行下一轮。

如果快速筛选没通过就计算x=x² mod n,最多计算s-1次。若某次计算x==n-1,则n可能是素数,本轮测试通过;如果x在所有幂次测试中都没有变成n-1,则n一定是合数,返回false

如果我们设置的20轮测试都通过,就认为n是一个素数。

 

我们回到密钥生成函数,得到pq以后计算nφ(n),然后进行e的选择。常用的e31765537,我们依次验证,如果与φ(n)互素就选择它。如果这三个常用的eφ(n)都不互诉,就从65537开始循环+2并判断直到找到符合条件的e

找到e后我们计算其模φ(n)的逆元d即私钥。

我们简单说一下求逆元的这个函数。原理是,当am互素,模m下存在a的逆元。利用广义欧几里得算法,可以求解出使ax+my=1成立的x值,x即为a在模m下的逆元。 

 扩展欧几里得算法的具体代码如图所示,这里不再赘述。

这样,我们就得到了公钥组en和私钥组dn,并将它们保存。

 

首先是加密函数,按要求设计传入参数为源文件路径,加密后目标文件路径,rsa公钥。

以逗号分割出公钥中的加密指数e和模数n

 

然后计算(明文+填充)块大小,单位是字节,这里我们要留出一个字节以确保块长度小于n,这是使用rsa算法必须满足的。

接着以二进制形式打开文件,确保能够处理任意格式的文件。

每个块分为明文和填充部分,留出至少11字节的填充空间,然后创建存放真正明文数据的buffer数组。

循环从文件中读入buffer数组大小个字节明文,然后对明文数据进行简单的 PKCS#1 填充。

填充的目的是扩展明文长度以适配块大小要求,并引入随机性以增强安全性。

这个填充的原理是怎么样的呢?对于每个块,先填上0x000x02,再填上一段非零随机填充,然后再加上一个分隔符0x00,最后接上明文数据。

代码中,首先用块大小减去明文长度再减3得到非零随机填充的长度。

然后添加固定的填充前缀。

 

生成非零随机填充长度个字节加进块中,再添加分隔符0x00和明文数据,得到最终的块中内容。 

 得到(明文+填充)块后,将它转换为大整数m,然后用模幂运算对大整数m进行加密。 

 模幂算法的具体实现使用的是信安数学中学的模重复平方法。代码如上,也不再赘述。

得到大整数密文c后,将其转换为字节数组写入中间文件中。

最后还要处理不完整块,因为如果前面的while循环最后一次读取到的数据小于buffer数组的大小,它会退出循环。

对剩余字节数,我们进行一样的操作,填充,转换为大整数并加密,加密完后将密文转换为字节数组并写入中间文件。

至此,加密过程结束。

 解密过程与加密类似,首先分割得到解密指数d和模数n,计算加密块大小,以二进制形式打开文件。

然后将读取到的中间文件中的字节数组转换为大整数,解密得到大整数m,将m转换为字节数组,去填充后写入最终文件即可。

这里不需要处理不完整块了,因为加密的时候每次得到的都是固定大小的块,所以解密时一定正好。

最后我们看一下去填充过程。由前面我们知道,填充格式为0x000x02,非零随机字节,分隔符0x00,明文数据。

对于每个块,我们首先定位到非零随机填充的开头,开始遍历,直到找到 0x00 分隔符,标志着明文开始,然后提取明文即可。

最后是代码封装。由于要求面向对象编程,所以写了个rsa类,其中public函数是密钥生成函数和加解密函数,private函数是其他内部辅助函数,仅暴露用户关心的生成密钥、加密、解密这三个核心功能,而隐藏内部实现细节。

Main函数中,先生成指定长度的密钥,然后分割成公钥和私钥。

再按要求进行加解密。

这就是本次rsa算法的全部实现。

首先,将初始明文存在当前文件夹下的plain.txt文件中,

然后,编译运行程序,终端会输出相应过程提示信息。

此时,当前文件夹下会生成加密后的二进制文件encrypted.bin也就是密文,以及解密得到的明文文件decrypted.txt

cat命令查看二进制密文文件,如图所示,乱码。打开解密得到的明文文件,可以看到,加解密过程成功完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值