实验四 Python综合实践
20184313 2019-2020-2 《Python程序设计》实验四报告
课程:《Python程序设计》
班级:1843
姓名:孙炜力
学号:20184313
实验教师:王志强
实验日期:2020年5月16日
必修/选修: 公选课
1.实验内容
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
我用python编程实现了国密算法SM9,实现了图形化客户端,为用户提供了公钥密码的加解密和签名验签功能,并验证具体实现中的优化效果。
2.实验要求
运用这学期所学的python所有知识来进行一个编程
(1)程序能运行,功能丰富。(需求提交源代码,并建议录制程序运行的视频)
(2)综合实践报告,要体现实验分析、设计、实现过程、结果等信息,格式规范,逻辑清晰,结构合理。
(3)在实践报告中,需要对全课进行总结,并写课程感想体会、意见和建议等。
2. 实验设计思路和结果
(1)SM9标识密码算法
SM9标识密码算法是一种基于双线性对的标识密码算法,于2015年发布为国家密码行业标准。它依据用户的身份标识生成用户的公、私密钥对,身份信息与密码算法关联,省去了数字证书、证书库和密钥库管理的流程。本节介绍所用算法的具体功能和软件优化实现。
符号和缩略语:
符号 |
含义 |
|
系统签名主私钥 |
|
系统签名主公钥 |
|
系统加密主私钥 |
|
系统加密主公钥 |
|
系统主公钥 |
|
系统主私钥 |
|
密钥生成函数识别符。这里默认为1 |
|
用户私钥,根据计算时参数不同分为加密私钥和签名私钥 |
|
用户公钥,根据计算时参数不同分为加密公钥和签名公钥 |
- 基本原理
SM9标识密码算法的数学工具是有限域群上椭圆曲线的点群运算及双线性对运算特性。设、为两个阶数为的加法循环群,为阶数为的乘法循环群,为质数且。、分别为、的生成元。
点群运算为基础,包括加法、多倍点两类。加法运算即、域元素的模加法,符号表述为:,其中。多倍点运算即椭圆曲线上同一个点的重复相加。
双线性对运算为映射。通过四类难解性问题确保算法安全。问题一,双线性逆(BIDH),给定,,计算困难。问题二,判定性双线性逆(DBIDH),给定,难以区分和。问题三,双线性逆(),给定, ,计算困难。问题4,双线性逆(),给定,,计算困难。
- 一般流程
系统为用户提供加解密和签名验签的功能。为了实现用户功能,除用户功能模块外,系统还提供了系统初始化、功能初始化和用户密钥派生模块。
系统初始化模块为用户初次使用提供初始化系统参数与循环群的功能。系统参数包括曲线的识别符、椭圆曲线基域的参数、中的两个元素和(它们定义椭圆曲线的方程:)、扭曲线参数以及上文提到的。在初始化循环群的过程中,由于循环群的阶数较大、元素较多,因此没有产生并保存完整的循环群,而是保存循环群的生成元、,并用元组保存。
功能初始化模块为用户提供生成系统主密钥的功能。分为加密初始化和签名初始化两个部分,分别产生系统加密主密钥、和系统签名主密钥和。用户每次签名验签和加解密之前,都要先生成相应的系统主密钥,并公开系统主公钥。
用户密钥派生模块用于把主密钥和用户标识结合,派生出用户密钥。分为用户私钥派生和用户公钥派生两个部分。分别派生用户加密私钥、用户签名私钥和用户加密公钥、用户签名公钥。
用户功能模块用于为用户提供加解密和签名验签的功能。
实际应用中,加解密和签名验签常同时进行,用户在产生、、和、后会将其打包为和系统主私钥,并公开。
- 哈希编码方式优化
在上述流程中的用户密钥派生模块和用户功能模块计算流程中,需要多次调用SM3杂凑函数计算哈希,在编程初期,我使用了gmssl库中的SM3算法。但该库中的SM3算法使用了列表(类似C的数组)来存储哈希的内容。在仔细观察其转化过程后,我注意到其转化过程为字符串到比特串再由循环转为整形列表。其最终目的是把字符型的变量转换为整型,方便计算。但上述转换的第一步产生的比特串型数据其实就已经把字符串转换为了整型,只是仍以字符串的形式保存。由于比特串型数据也可以向序列一样实现随机访问,且使用序列存储会占用比较大的空间并需要额外的转换过程,因此比特串的编码方式既满足要求,也降低了时间和空间复杂度。
因此我修改了相关代码,并替换了SM3函数,免去了从比特串向列表的转换,使得哈希明文格式转换的时间复杂度由降低为。
- 密钥生成编码方式优化
在上述流程中的功能初始化模块、用户密钥派生模块和用户功能模块计算流程中,需要调用密钥生成函数,从交互双方共享的比特串中派生出密钥数据。因此需要把字节串型的数据转换为比特串进行操作。由于python没有比特串型数据,因此实际上是在字节串的基础上对比特位进行操作。因此需要把字符串转换为字节串。前期我使用python中的bytes列表来存储转换结果。之后发现在SM9密钥生成算法中要转换的字符串是16进制的,如果用一般的encode方法(从utf-8转为比特串)并转为列表会浪费较大空间(一个字符占用8位存储空间),并且在计算时会增加待处理数据的长度,增加运行时间。
经过思考,改为使用从16进制字符串转为16进制比特串的方法进行转换(一位16进制占用4位空间),这样转换使得转换后的结果分量与相应数据存储区的各比特一一对应,更加符合国标,同时也降低了时间和空间复杂度。
例如在下图对应的例子中,原方案把字符串’4d’视为字符,用utf-8编码后占用2字节空间,后续计算时,须进行2次循环,时间复杂度为。改进后我将其视为16进制的数字,转换后为2位16进制,占用1字节空间,后续计算时,须进行1次循环,时间复杂度为。
(2)SM9标识密码算法优化分析
我设计了SM9标识密码算法的python软件优化实现。本节将分别针对密钥派生、签名验签、加密解密设计实验,验证优化效果。采用方案A,基于python中的bytes结构,逐字节处理数据,借助整型完成按位异或等布尔运算。同时,通过数学推理优化密钥导出及杂凑辅助函数。方案B用于对照,运算过程涉及字符数据,没有通过数学推理进行计算优化。
以签名私钥为例,测量方案A和方案B的密钥派生时间。实验中,用户标识随机生成,共6串字符,长度均在20以内,记。受硬件状况、外界环境等因素影响,代码运行时间在小范围内波动。因此,对于,均采用测量6次取平均值的方式减少误差。分别测量各方案产生签名私钥所用时间,计算平均值,结果如表1所示:
表1:各方案密钥派生所用时间
|
|
|
|
158.50 |
227.69 |
|
190.36 |
262.39 |
|
204.84 |
294.60 |
|
177.11 |
340.47 |
|
190.48 |
260.33 |
|
176.18 |
294.58 |
分别执行签名、验签算法,测量方案A、方案B每分钟运算次数。实验编码环境为UTF-8。待处理信息相同。对于签名算法,所使用为长度256位的SM3杂凑计算结果,该结果直接参与签名运算,以排除杂凑算法对实验干扰。对于验签算法,所使用为上述信息的签名内容。连续执行,记录各方案每分钟运算完成次数 ,如表2所示。
表2签名验签运算次数对比
|
|
|
签名 |
336 |
304 |
验签 |
62 |
59 |
分别执行加密、解密算法,测量方案A与方案B的加密、解密速率。随机生成10串字符,所占字节 。对于,各方案使用同组密钥,交替执行6组加密、解密运算,记录每次加密运算所用时间 ,每次解密运算所用时间 。计算每秒加密字节数量,即加密速率,计算每秒解密字节数量,即解密速率,结果如表3所示:
表3:各方案加密解密速率
|
|
|
|
|
1 |
602.05 |
548.72 |
426.08 |
368.30 |
2 |
673.63 |
590.69 |
486.54 |
475.37 |
3 |
636.12 |
571.77 |
547.85 |
467.43 |
4 |
592.52 |
558.54 |
507.40 |
500.41 |
5 |
641.66 |
601.28 |
523.50 |
476.30 |
6 |
642.47 |
605.85 |
500.34 |
467.72 |
7 |
615.41 |
538.48 |
466.77 |
473.19 |
8 |
564.05 |
537.23 |
505.58 |
476.03 |
9 |
583.13 |
576.28 |
504.51 |
458.77 |
10 |
591.59 |
573.38 |
482.50 |
475.33 |
由图1可见,方案A加密、解密速率均大于方案B。且均保持稳定,不随明文长度增加而显著变化。更进一步,计算平均值,标准差 。攻击者难以通过加密、解密速率变化推测密钥长度。
图1:各方案加密解密速率随明文长度变化
扩散(diffusion)要求明、密文关系尽量复杂,明文中任何一点小更动都会使密文有很大差异[40]。据此设计实验,验证加密算法安全性本身,并没有因方案A所做优化而破坏。随机生成一串字符,长度为100。控制明文与密钥不变,分别进行3组实验,随机生成字符,替换明文中的k个,。对于,进行6次实验,每次明文字符变化个数相同,但内容与位置随机。计算字符改变数的均值与标准差,离散分布如表4所示:
表4:方案A密文字符变化
k |
mean ± SD |
1 |
|
2 |
|
3 |
|
实验中,明文发生改变,密文均会产生巨大变化。密文字符改变数量均在90以上,占比超过90%。可见明文扩散性较好,方案A所做优化并没有破坏算法安全性。
综上,本节设计实验,验证SM9标识密码算法python软件优化效果。密钥派生中,使用不同用户标识产生签名私钥,用时更少。签名验签中,分别实验,连续执行签名、验签算法,每分钟运算次数更多。加密解密中,明文长度不同,进行多组加密解密运算,速率更快。同时,明文扩散性较好,安全性没有受到破坏。
码云链接:https://gitee.com/sun_wei_li/SWL-20184313/blob/master/sy4/sy4.py
3.实验过程中遇到的问题和解决过程
问题一:一开始用户公钥的保存序列的初始化使用a=b=[],之后发现a、b之间是相互影响的,a的变化就会使得b发生变化。(这里a、b是代指)
问题一解决:将a、b的初始化语句分开。
问题二:在打印用户列表时需要在列表最后拼接一项添加以方便用户使用,一开始使用k.append(‘添加’),结果返回None
问题二解决:k.append()是直接对k进行修改,没有返回值,因此需要先把k赋值给一个a,然后对a进行拼接或添加。
问题三:在加密部分明文是会失败
问题三解决:经过单步调试,发现我改动后的SM3算法省略了前导0,对于一些明文哈希后得到63位结果,导致错误。最后用format方法补前导0,问题得以解决。
其他(感悟、思考等)
这次的实验是一次综合实验,由于这一学期我刚好同时学习python和密码学,因此我平时的密码学实验都是由python编写的,因此对python的一些密码学的数学方法有一定的编程基础,故选择SM9算法进行实践。本次实验的SM9算法实现程度较好,也通过实验测试了其优化后的性能。但本次实验也存在一些不足之处。我最初的想法是做一个用户界面来实现微信消息的自动加解密,但这需要使用itchat库,但该库是基于微信网页版,而目前微信网页版已经不能登录,因此没能实现更方便的功能。这是本次实验比较遗憾的一点。
这学期的python课程至此已经结课。通过这学期对于python的学习,我掌握了很多python的编程技巧,同时也认识到了python的简洁与强大。比如说我在咱们学校学习过c、python和java,但我发现python即使是选修课,也能比c和java实现更多的功能,还有就是在平时的密码学实验中,我的python代码总能比其他同学的c要更少,且更容易实现图形化界面。以上是我认识到的python的优点,但我也发现了一些不足之处。由于python是解释性的语言,虽然它语法简单、更容易上手,但我发现它的运行速度要比c和java慢,所以c和java多用于编写系统的核心代码,而python常用于编写一些脚本。这是我这学期学习python的最大感悟。下面是我的一些建议。
本学期的课程我非常满意,但有一点小小的建议。我认为老师可以多向我们提供一些帮助和指导,并适当延长作业提交时间。
在python文件操作的加分彩蛋中,我需要安装一些外部库,但我的电脑由于缺少一些软件而无法安装成功,由于当时比较晚,且提交时间紧迫,因此没有完成。我认为老师可以适当延长这些加分作业的提交时间,给足时间来处理一些环境的问题。