Mathematica应用技术-实验指导书_第1页
Mathematica应用技术-实验指导书_第2页
Mathematica应用技术-实验指导书_第3页
Mathematica应用技术-实验指导书_第4页
Mathematica应用技术-实验指导书_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

PAGEXIVPAGE2《Mathematica应用技术》实验指导书张勇主编软件与通信工程学院学术委员会审2024年2月

目录TOC\o"1-3"\h\u第一部份绪论 1一、本课程实验的作用与任务 1一、本课程实验的基础知识 1二、本课程实验教学项目及其教学要求 1第二部份基本实验指导 3实验一Wolfram字符串操作 3一、实验目的 3二、实验原理 3三、主要仪器及耗材 3四、实验内容与步骤 4五、实验注意事项 6六、思考题 6实验二Wolfram中英文字符或单词统计 7一、实验目的 7二、主要仪器及耗材 7三、实验内容与步骤 7四、实验注意事项 10五、思考题 10实验三Wolfram绘制Lorenz动态演化曲线 11一、实验目的 11二、主要仪器及耗材 11三、实验内容与步骤 11四、实验注意事项 12五、思考题 12实验四Wolfram求解定积分 13一、实验目的 13二、主要仪器及耗材 13三、实验内容与步骤 13四、实验注意事项 15五、思考题 15实验五SM4加密与解密图像 16一、实验目的 16二、实验原理 16三、主要仪器及耗材 17四、实验内容与步骤 17五、实验注意事项 28六、思考题 28参考文献 29第一部份绪论本指导书是根据《Mathematica应用技术》课程实验教学大纲编写的,适用于电子通信、软件工程、物联网工程等相关专业。本课程实验的作用与任务该实验课程是加深学生了解Mathematica应用、掌握Wolfram语言的必不可少的一项实践活动。该课程通过对基于Mathematica的Wolfram语言编程的学习,使学生能够规范Wolfram语言程序格式,对怎样来利用Wolfram语言编写程序?对函数式编程是怎样一个过程?如何利用Wolfram语言将实际问题转化为数学模型并求解?”等问题有一个清晰的回答,帮助学生建立使用Wolfram语言有整体概念,提高学生的提高学生的Wolfram语言综合运用能力,掌握Wolfram语言的编程技巧,具备初步的编写中小规模的Wolfram语言程序的方法,掌握Wolfram语言的调试技巧和拓展技术。通过实验培养学生将实际问题转化为数学模型并求解的能力,激发学生学习Wolfram语言的乐趣,实现学以致用的最终目的。以此巩固并加深对本课程基本知识的理解,增强感性认识,为后续专业课程的学习打下坚实的基础。本课程实验的基础知识《Mathematica应用技术》课程要求已经修过《高等数学》、《线性代数》和《C/C++语言程序设计》等课程或者已经储备了相关的专业知识。本课程实验教学项目及其教学要求序号实验项目名称学时实验类型教学目标、要求1Wolfram语言字符串操作3验证性实验熟悉Mathematica软件工作环境;掌握Wolfram语言的常用字符串操作函数;学会基于Wolfram语言进行字符串的合并与拆分操作;熟悉Wolfram语言中函数的使用与参数设置;能利用Wolfram语言内置函数实现一些简单程序。2Wolfram中英文字符或者单词统计3验证性实验掌握Wolfram语言中列表的构造方法;熟练掌握列表元素操作函数及其用法;学会从外部导入数据到Mathematica中能正确处理导入到Mathematica中数据的内容和格式理解Mathematica中数据匹配3Wolfram绘制Lorenz动态演化曲线3验证性实验掌握利用Mathematica常用的二维三维绘图函数掌握在Mathematica中定义各类数学函数的方法在Mathematica中能自行调整绘图显示和各类标注能利用Mathematica编写动态图形显示的程序讨论一些使得利用Mathematica绘图更加美观函数选项4Wolfram求解定积分3验证性实验掌握Wolfram语言计算不定积分和定积分的方法;掌握Wolfarm语言计算导数和方向导数的方法;讨论各类数学函数如何方便地利用wolfram语言表示并输入到Mathematica中利用Wolfram语言求解学习中遇到的数学问题5SM4加密与解密图像4验证性实验熟练掌握Module模块程序设计方法;掌握Compile模块编译技巧和程序设计方法体会并讨论使用Complie模块编译的所带来的程序设计优势分析和理解SM4加密算法的原理;学会应用SM4对数据进行加密与解密合计16第二部份基本实验指导实验一Wolfram字符串操作实验目的熟悉Mathematica软件工作环境;掌握Wolfram语言常用的字符串操作函数;利用Wolfram语言编写并实现对字符串的基本操作。实验原理Wolfram语言中所有的表达式都是由少量不同类型的原子元素构建,字符串就是其中之一。Wolfram语言中创建字符串类型时需在输入时伴随双引号。Mathematica软件具有强大的字符串处理功能,其内置了许多字符串处理函数,借助这些函数我们可以轻松地实现对字符串的操作。在Notebook中输入“str1="Student"”和“str2="textbook"”,并执行得到两个字符串str1和str2,以这两个字符串示例,用于部分字符串函数及其典型用法如表1-1所示。表1-1Mathematica中部分字符串函数及其典型用法序号函数名典型示例结果1求字符串长度StringLengthStringLength[str1]72求字符串中的字符列表CharactersCharacters[str1]{S,t,u,d,e,n,t}3连接字符串<>str1<>str2Studenttextbook4连接字符串StringJoinStringJoin[str1,str2]Studenttextbook5字符串中的字符大写ToUpperCaseToUpperCase[str1]STUDENT6字符串中的字符小写ToLowerCaseToLowerCase[str1]student7字符串反序排列StringReverseStringReverse[str1]tnedutS8用空格分离字符串StringSplitStringSplit["abcdefg"]{ab,cd,efg}9用逗号和空格分离字符串StringSplit[字符串,","]StringSplit["ab,cd,efg",","]{ab,cd,efg}三、主要仪器及耗材计算机一台。实验内容与步骤实验内容:运行Mathematica软件并建立新的notebook文件;编写Wolfram程序并实现2、3、4的要求;给定一个字符串列表,将其合并为一个字符串;给定一个字符串,将其以空格或逗号为分隔符分隔为各个单词的列表;给定一个字符串,例如“abcdefghijk”,找到字符“f”的位置;验证程序运行结果是否正确。实验步骤:熟悉Mathematica软件在Windows系统桌面上用鼠标双击“WolframMathematica”图标后进入Mathematica启动界面,如图1-1所示。图1-1Mathematica启动界面在此界面中,“RECENTFILES”显示最近打开的笔记本,右下角的“Showatstartup”默认为选中态,表示每次启动Mathematica均显示Mathematica启动界面。在图1-1中,用鼠标左键单击“NewDocument”,会创建一个新的notebook文件并进入图1-2所示界面。图1-2Mathematica笔记本界面在图1-2的界面中,最上方为标题栏,显示当前文件的名称以及WolframMathematica版本号,第二行为菜单栏,菜单栏包含了开发环境中几乎所有的命令,它为用户提供了文档操作、程序的编译、调试、窗口操作等一系列的功能。下方空白处为文档窗口,在此处可进行程序的编写并得到运行结果。验证实验内容(1)给定一个字符串列表,将其合并为一个字符串如图1-3所示,在文档窗口中先输入“str1={"abc","123","XYZ","@#$"};”,定义好一个字符串列表。然后在第二行调用字符串连接函数StringJoin,将原定义的字符串列表合并为一个字符串并保存在“str2”中。运行程序得到结果为第三行。在得到结果后,调用StringQ函数来验证是否得到了合并后的结果是否为一个字符串,可以看到“str1”不是一个字符串而“str2”是一个字符串。图1-3合并字符串列表(2)给定一个字符串,将其以空格或逗号为分隔符分隔为各个单词的列表如图1-4所示,第一行定义一个含有空格的字符串str3,在第二行以缺省的方式直接调用StringSplit函数默认将字符串以空格为分隔符将其分隔为各个单词的列表,在第三行可以看到字符串列表“str3”中的各个单词分隔成功;第四行调用StringSplit函数以逗号为分隔符将其分隔为各个单词的列表,并在第五行可以看到字符串“str3”中以逗号连接处断开,形成分隔,而空格依然存在图1-5分隔字符串中的单词(3)给定一个字符串,例如“abcdefghijk”,找到字符“f”的位置如图1-6所示,调用StringPosition函数,参数的第一个位置给定字符串,第二个位置要查找的字符,运行后可得到的结果为所需查找字符串在给定字符串中的起始位置和结束位置所形成的列表,由于查找的为单个字符,所以起始位置与结束位置相同。图1-6查找字符的位置实验注意事项定义字符串时需注意一定要带双引号。正确认识字符串与字符串列表的区别。StringSplit函数不会返回字符串子串中的空格、制表符和回车之类的空白分隔符。思考题如何在在合并字符串时在字符串之间增加一个新行?如何将一个字符串和一个数字合并成一个新的字符串?

实验二Wolfram中英文字符或单词统计实验目的掌握Wolfram语言中各类列表的创建方法能熟练使用Wolfram语言中各种列表元素操作函数及其用法编写列表处理程序二、主要仪器及耗材计算机一台。三、实验内容与步骤实验内容:构建特定类型的列表;编写Wolfram程序实现3、4、5的要求。给定一个字符串列表,统计其中某个单词出现的频率使用WordList函数,统计英文单词的首字母出现的频率。给定一个字符串,统计其中的中文字符数、英文字符串和数字个数。验证编写程序的结果实验步骤:(1)给定一个字符串列表,统计其中某个单词出现的频率如图2-1所示,首先新建一个TXT格式的文件,并在其中写入一段英文,这里写入的英文是《LittlePrince》的第21章。然后如图2-2所示,第一行为利用Import函数将其导入到Mathematica中,其中参数为所要导入文件的绝对路径。在第二行和第三行借由StringQ函数可以看到导入后是一个字符串,因此需要用TextWords函数将其分隔为字符串列表。最后如图2-3所示,可以利用Count函数对字符串列表“strlist”中的单词“fox”和“prince”出现的频率进行统计。图2-1建立的TXT文件图2-2创建字符串列表图2-3对特定单词出现次数进行统计(2)使用WordList函数,统计英文单词的首字母出现的频率如图2-4所示,第一行WordList函数缺省使用时默认会给出常见单词的字符串列表,因此在统计单词首字母出现的频率前需对该列表进行处理。先使用StringTake函数将WordList函数生成的单词列表中第“1”个字母提取出来,提取完单词首字母后再在其外套一层Counts函数得到首字母出现的频率。最后可以看到得到了出现的每个单词首字母及其在WordList函数中的出现的频率图2-4,提取常见单词首字母出现频率(3)给定一个字符串,统计其中的中文字符数、英文字符串和数字个数。如图2-5所示,首先定义了一个包含英文、中文和数字的字符串str1;再利用StringSpilt函数,以非字母和数字作为条件分隔字符串,在此过程中去掉了原字符串中的空格和各种标点符号,得到了仅含有中文字符、英文字符和数字的字符串列表。接着利用Characters函数将原字符串列表更加细化为由单个字符字符串组成的嵌套列表,并利用Flatten函数解除一层嵌套。然后使用StringCases将非字母字符即数字提取出来,在使用Flatten函数使得提取出的数字变成单层列表后利用Length函数求数字列表长度即为原字符串str1中数字个数。在得到数字个数后,使用同样的方法提取出仅含有中文字符的单层列表求得中文字符个数并保存在变量chinesenum中。最后用只包含中文字符、英文字符和数字的字符串列表长度减去数字个数和中文字符个数即可得到英文字符个数。图2-5各类字符统计实验注意事项从外部导入数据到Mathematica中时需正确判断其类型。LetterCharacter函数所匹配的字母包括各类语言的字母,也包含中文字符。思考题如何使用StringSplit函数将上述TXT文件的字符串转化为英文单词字符串列表?如何使用Count函数得到与Counts函数一样的结果?

实验三Wolfram绘制Lorenz动态演化曲线实验目的熟练掌握Mathematica中常用的绘图函数;掌握Mathematica中调整绘图效果的选项技术;能自主编写简单图形动态显示程序。二、主要仪器及耗材计算机一台。三、实验内容与步骤实验内容:1.已知Lorenz方程如下式所示:&x其中,σ=10,r=28,b=8/3。将上式用差分方程表示,时间步长取为0.002。使用Animate函数或Manipulate函数实现Lorenz方程的相图演变动画;实验步骤:先根据欧拉公式将Lorenz方程转变为差分方程,Lorenz方程的差分方程如下式所示:&如图3-1所示,使用自定义函数将该差分方程利用Wolfram语言表示出来。该处语句将Loren差分方程定义为一个纯函数,“#[[1]]”、“#[[2]]”和“#[[3]]”分别代表该纯函数待传入参数列表中的第一、二、三个元素,即表示差分方程组中的x、y和z。纯函数花括号内第一个表达式为差分方程组中的第一个方程右边的内容xn-1+t-σx-y,该表达式在接收参数后会计算出结果并作为返回列表中的第一个参数即差分方程组中的xn;花括号内的另两个表达式同理在计算完后分别返回差分方程组中的yn和zn。之后利用NestList函数迭代计算20000次,得到包含初始值在内的20001组xn、y得到数据后,利用Animate函数将计算得到的坐标值以动画的方式展示出来。Animate函数中的第一个参数ListPointPlot3D[data[[301;;𝑡]],表示动画的内容是一个根据列表data中数据绘制的三维点图,数据从data中的第302项到第t项,t作为动画的变化值。第二个参数指定了坐标轴的标签x、y、z,并使用倾斜字体样式,第三个参数指定了该动画界面的大小为中等,第四个参数指定了坐标轴上数值采用16号"TimesNewRoman"字体,第五个参数“{𝑡,302,20000,1}”表示变化值t的取值以步长为1的方式从302变化到20000;最后两个选项则指定了动画进行速率和播放动画方式。四、实验注意事项NestList函数的所返回计算结果列表的第一项初始值。需要合理选择Animate绘图函数中的参数,使得动画美观流畅。五、思考题如何给动画增加一个标题,提醒该动画所展示的内容?如何使得Lorenz相图动画后出现的点与之前出现的点颜色不同,以便区分?

实验四Wolfram求解定积分实验目的掌握Wolfram语言计算积分的方法;掌握Wolfram语言计算导数的方法;能运行Wolfram语言解决给定的数学中微积分问题主要仪器及耗材计算机一台。实验内容与步骤实验内容:求解函数Sin(x2)在区间[0,3]上的定积分;设fx=x2+x+1,求由直线实验步骤:(1)求解函数Sin(x2)在区间[0,3]上的定积分如图4-1所示,直接利用积分函数Integrate对函数Sin(x2)在区间[0,3]上的定积分进行求解,Integrate函数中第一个参数为表达式,此处为Mathematica中内置的Sin函数,Sin函数的参数为自变量x2;第二个参数为自变量x的取值范围[0,3]。在第二行可以得到一个精确解,但该解中包含了一个菲涅尔积分,因此在第三行使用N函数对存储在“y”中的精确解求其数值解,得到其六位精度的数值解0.773563。最后可以利用二维绘图Plot函数得到所求求解的定积分图像,Plot第三个参数为曲线向坐标轴方向填充。图4-1求解定积分(2)设fx=x2+x+1如图4-2所示,先利用Plot函数,观察所求曲边梯形区域,再利用Integrate函数求得曲边梯形面积。图4-2求曲边梯形面积实验注意事项Sin函数为Mathematica内置函数,首字母要大写,参数用方括号。使用Plot函数时得正确使用填充区域。思考题如何x2Sin2x的不定积分?如何求解心形线与极轴围成的面积?

实验五SM4加密与解密图像实验目的熟练掌握Mathematica中Module模块程序设计方法学会利用Mathematica编写复杂程序了解SM4加密实现原理与算法学会利用SM4算法对数据进行加密与解密实验原理商用密码SM4是我国的一项文本数据加密标准,输入密钥长度为128比特,输入的明文长度为128比特,输出的密文长度也为128比特。SM4密码的工作原理包括两部分,即加密算法和密钥扩展算法。SM4的解密算法与加密算法相同,但是输入为密文c,且轮密钥rk的输入顺序与加密算法相反,即依次输入rk31,rk30,…,rk0.设轮密钥rk已经由图7-8生成就绪,下面首先介绍图7-7所示的SM4密码的加密过程:第1步:将输入明文p分为4个32比特的字,记为x0、x1、x2和x3。第2步:第1轮操作,x4=x0⨁L1(T(x1⨁x2⨁x3⨁rk0))第3步:依次执行第2轮至第32轮操作,其中,第i轮将生成一个新的xi+3,即xi+3=xi-1⨁L1(T(xi⨁xi+1⨁xi+2⨁rki-1))第4步:将第32轮的输出按字节左右翻转,得到密文c,即c=(x35,x34,x33,x32)。上述的“⨁”表示按位异或。在上述的第2步和第3步中,即在每一轮中,都使用了变换T和L1,这里的T表示查表操作,而L1是基于字的移位异或操作。其中,变换L1的运算如下:y=L1(x)=x⨁(x<<<2)⨁(x<<<10)⨁(x<<<18)⨁(x<<<24)其中,“<<<”表示循环左移位。变换T的运算如下:y=T(x)=T(x(31:24),x(23:16),x(15:8),x(7:0))=(Sbox(x(31:24)),Sbox(x(23:16),Sbox(x(15:8)),Sbox(x(7:0)))即T变换的过程为先将输入x分为四个字节,然后,根据S盒子查找每个字节的变换值,再将变换后的值合并,记为y。这里的S盒子为16×16的二维数组(或者视为一个长度为256的向量)主要仪器及耗材个人PC机一台。实验内容与步骤实验内容:编写Module模块程序实现SM4加密和解密算法;编写Module模块程序实现CBC模式下的SM4加密与解密处理;使用密钥k1=“C1E7DA73EFA036FD7343CE282145A61A”,k2=“C1E7DA73EFA036FD7343CE282145A61B”加密以下图像并解密。图1.Lena图像图2.Pepper图像实验步骤:(1)SM4加密和解密算法依据课本上7.5.2节的程序实例,如下所示先编写SM4算法密钥扩展函数keyext;1keyext[k_]:=Module[2{key=k,ck,fk,fk1,key1,key2,y,yt,rk,sbox,t1,t2,t3,t4,t5,t6,t7},3ck=Table[0,32];4Table[ck[[i+1]]=Mod[4i*7,256]*2^24+Mod[(4i+1)*7,256]*2^16+5Mod[(4i+2)*7,256]*2^8+Mod[(4i+3)*7,256],{i,0,31}];6fk={"A2B1BAC6","56AA3350","677D9197","B27022DC"};7fk1=FromDigits[#,16]&/@fk;8key1=StringPartition[key,8];9key2=FromDigits[#,16]&/@key1;10y=BitXor[key2,fk1];11yt=Table[0,4];12rk=Table[0,32];13sbox={214,144,233,254,204,225,61,183,22,182,20,194,40,14251,44,5,43,103,154,118,42,190,4,195,170,68,19,38,1573,134,6,153,156,66,80,244,145,239,152,122,51,84,11,1667,237,207,172,98,228,179,28,169,201,8,232,149,128,17223,148,250,117,143,63,166,71,7,167,252,243,115,23,18186,131,89,60,25,230,133,79,168,104,107,129,178,113,19100,218,139,248,235,15,75,112,86,157,53,30,36,14,94,2099,88,209,162,37,34,124,59,1,33,120,135,212,0,70,2187,159,211,39,82,76,54,2,231,160,196,200,158,234,22191,138,210,64,199,56,181,163,247,242,206,249,97,21,23161,224,174,93,164,155,52,26,85,173,147,50,48,245,24140,177,227,29,246,226,46,130,102,202,96,192,41,35,25171,13,83,78,111,213,219,55,69,222,253,142,47,3,255,26106,114,109,108,91,81,141,27,175,146,187,221,188,27127,17,217,92,65,31,16,90,216,10,193,49,136,165,205,28123,189,45,116,208,18,184,229,180,176,137,105,151,2974,12,150,119,126,101,185,241,9,197,110,198,132,24,30240,125,236,58,220,77,32,121,238,95,62,215,203,57,72};31Table[yt[[1]]=y[[2]];yt[[2]]=y[[3]];yt[[3]]=y[[4]];32t1=BitXor[ck[[i]],y[[2]],y[[3]],y[[4]]];33t2={Floor[t1/2^24],Mod[Floor[t1/2^16],256],34Mod[Floor[t1/2^8],256],Mod[t1,256]};35t3={sbox[[t2[[1]]+1]],sbox[[t2[[2]]+1]],36sbox[[t2[[3]]+1]],sbox[[t2[[4]]+1]]};37t4=t3[[1]]*2^24+t3[[2]]*2^16+t3[[3]]*2^8+t3[[4]];38t5=IntegerDigits[t4,2,32];39t6=FromDigits[RotateLeft[t5,13],2];40t7=FromDigits[RotateLeft[t5,23],2];41yt[[4]]=BitXor[y[[1]],t4,t6,t7];42y=yt;43rk[[i]]=y[[4]]44,{i,1,32}];45rk46]该代码的第1行用于定义keyext函数的名称,参数有输入密钥k,第2行为定义keyex函数的Module模块中所使用的的局部变量。第3~4用于生成密钥扩展算法中所需要的参数ck。第6行是设置系统参数fk,并在第7行利用纯函数“FromDigits[#,16]&”将fk中的每一个字符串转换成对应的十进制整数,得到一个长度为4的整数数组fk1。第8~9行将输入的密钥k同样地转化为整数数组保存在key2中。第10行是将对key2和fk1进行异或运算,两个数组对应位置的整数进行异或操作,得到初始的y值。第11和12行分别初始化了变量yt和rk,yt用于暂存每一轮循环中y的值,rk用于存储轮密钥并在Module模块结尾作为函数的返回值。第13~30行为数组sbox,是SM4算法的S盒。第31~44行使用Table函数实现32轮的循环操作,第44行的“{i,1,32}”表示循环变量i从1开始每轮自加1到32结束。第31~43行表示在第i轮操作中,先将数组y的第2、3和4个元素依次赋给变量yt的第1、2和3个元素(第31行);然后,将ck[i]与y[2]、y[3]、y[4]一起异或得到变量t1(第32行);将长度为32比特的t1分成4个字节,保存在变量t2中(第33~34行)。根据t2各个元素的值,因为S盒中行列从0开始,而在Mathematica中列表元素位置从1开始,因此查S盒需在t2中的值的基础上加1,查S盒得到新的变量t3(第35~36行);将t3中四个8比特长度的元素转化为一个长度为32比特的变量t4(第37行);第38行用IntegrateDigits函数以不足左补零的方式将t4转化为长度为32的二进制序列字符串,保存在t5中;第39行将t5左循环移位13位,并转化为十进制整数保存在t6中;第40行将t5左循环移位23位,然后转化为整数保存在t7中;接着,第41行异或y[1]、t4、t6和t7得到yt[4];第42行将yt赋给y,为下一次循环做准备;第43行将y[4]赋给rk[i],即得到第i轮的轮密钥。第44行表示上述过程循环执行32次,从而得到完整的轮密钥rk。第45行返回轮密钥rk。再编写加密函数sm4en,最后编写解密函数sm4de,加解密函数均需要用到密钥扩展函数。加密函数代码如下所示。1sm4en[k_,p_]:=Module[2{key=k,p1=p,rk,sbox,p2,x,xt,t1,t2,t3,t4,t5,t6,t7,t8,t9,c1,c},3rk=keyext[key];4sbox={214,144,233,254,204,225,61,183,22,182,20,194,40,5251,44,5,43,103,154,118,42,190,4,195,170,68,19,38,673,134,6,153,156,66,80,244,145,239,152,122,51,84,11,767,237,207,172,98,228,179,28,169,201,8,232,149,128,8223,148,250,117,143,63,166,71,7,167,252,243,115,23,9186,131,89,60,25,230,133,79,168,104,107,129,178,113,10100,218,139,248,235,15,75,112,86,157,53,30,36,14,94,1199,88,209,162,37,34,124,59,1,33,120,135,212,0,70,1287,159,211,39,82,76,54,2,231,160,196,200,158,234,13191,138,210,64,199,56,181,163,247,242,206,249,97,21,14161,224,174,93,164,155,52,26,85,173,147,50,48,245,15140,177,227,29,246,226,46,130,102,202,96,192,41,35,16171,13,83,78,111,213,219,55,69,222,253,142,47,3,255,17106,114,109,108,91,81,141,27,175,146,187,221,188,18127,17,217,92,65,31,16,90,216,10,193,49,136,165,205,19123,189,45,116,208,18,184,229,180,176,137,105,151,2074,12,150,119,126,101,185,241,9,197,110,198,132,24,21240,125,236,58,220,77,32,121,238,95,62,215,203,57,72};22p2=StringPartition[p1,8];23x=FromDigits[#,16]&/@p2;24xt=Table[0,4];25Table[xt[[1]]=x[[2]];xt[[2]]=x[[3]];xt[[3]]=x[[4]];26t1=BitXor[rk[[i]],x[[2]],x[[3]],x[[4]]];27t2={Floor[t1/2^24],Mod[Floor[t1/2^16],256],28Mod[Floor[t1/2^8],256],Mod[t1,256]};29t3={sbox[[t2[[1]]+1]],sbox[[t2[[2]]+1]],30sbox[[t2[[3]]+1]],sbox[[t2[[4]]+1]]};31t4=t3[[1]]*2^24+t3[[2]]*2^16+t3[[3]]*2^8+t3[[4]];32t5=IntegerDigits[t4,2,32];33t6=FromDigits[RotateLeft[t5,2],2];34t7=FromDigits[RotateLeft[t5,10],2];35t8=FromDigits[RotateLeft[t5,18],2];36t9=FromDigits[RotateLeft[t5,24],2];37xt[[4]]=BitXor[x[[1]],t4,t6,t7,t8,t9];38x=xt39,{i,1,32}];40x=Reverse[x];41c1=IntegerString[#,16,8]&/@x;42c=ToUpperCase[StringJoin[c1]]43]函数sm4en为SM4密码的加密函数,输入为密钥k和明文p,输出为密文c。第2行定义Module模块内部使用的局部变量。第3行调用keyext函数由密钥key生成轮密钥rk。第4~21行为S盒数组sbox,其中的数据来自于表7-19。第22行将输入的明文p1分成8个字符一组的列表p2;第23行将p2转化为整数数组。第24行定义变量xt,用于在各轮的循环中暂存x。第25~39行为借助于Table的循环操作,对应着SM4的轮操作,对于第i轮而言,首先将x的第2、3、4个元素依次赋给xt的第1、2、3个元素(第25行);然后,将第i轮的轮密钥rk[i]与x[2]、x[3]、x[4]相异或得到t1;第27~28行将长度为32比特的t1分成4个字节,保存在列表t2中;第29~30行根据t2查询S盒得到新的列表t3;第31行将4个8位的列表t3合并一个长度为32位的整数,保存在t4中;第32行将t4转化为二进制数字符数组t5;第33行将t5循环左移2位后转化为整数,保存在t6中;第34行将t5循环左移10位后转化为整数,保存在t7中;第35行将t5循环左移18位后转化为整数,保存在t8中;第36行将t5循环左移24位后转化为整数,保存在t9中;第37行将x[1]、t4、t6、t7、t8和t9的异或结果赋给xt[4];第38行将xt赋给x,为下一轮循环作准备;第39行说明上述操作循环32次。第40行将Table计算的结果x左右翻转后仍赋给x。第41行将x转化为字符数组,赋给c1;第42行将c1合并为一个字符串,赋给c,c即为密文。解密函数sm4de如下所示:1sm4de[k_,p_]:=Module[2{key=k,p1=p,rk,sbox,p2,x,xt,t1,t2,t3,t4,t5,t6,t7,t8,t9,c1,c},3rk=Reverse[keyext[key]];4sbox={214,144,233,254,204,225,61,183,22,182,20,194,40,5251,44,5,43,103,154,118,42,190,4,195,170,68,19,38,673,134,6,153,156,66,80,244,145,239,152,122,51,84,11,767,237,207,172,98,228,179,28,169,201,8,232,149,128,8223,148,250,117,143,63,166,71,7,167,252,243,115,23,9186,131,89,60,25,230,133,79,168,104,107,129,178,113,10100,218,139,248,235,15,75,112,86,157,53,30,36,14,94,1199,88,209,162,37,34,124,59,1,33,120,135,212,0,70,1287,159,211,39,82,76,54,2,231,160,196,200,158,234,13191,138,210,64,199,56,181,163,247,242,206,249,97,21,14161,224,174,93,164,155,52,26,85,173,147,50,48,245,15140,177,227,29,246,226,46,130,102,202,96,192,41,35,16171,13,83,78,111,213,219,55,69,222,253,142,47,3,255,17106,114,109,108,91,81,141,27,175,146,187,221,188,18127,17,217,92,65,31,16,90,216,10,193,49,136,165,205,19123,189,45,116,208,18,184,229,180,176,137,105,151,2074,12,150,119,126,101,185,241,9,197,110,198,132,24,21240,125,236,58,220,77,32,121,238,95,62,215,203,57,72};22p2=StringPartition[p1,8];23x=FromDigits[#,16]&/@p2;24xt=Table[0,4];25Table[xt[[1]]=x[[2]];xt[[2]]=x[[3]];xt[[3]]=x[[4]];26t1=BitXor[rk[[i]],x[[2]],x[[3]],x[[4]]];27t2={Floor[t1/2^24],Mod[Floor[t1/2^16],256],28Mod[Floor[t1/2^8],256],Mod[t1,256]};29t3={sbox[[t2[[1]]+1]],sbox[[t2[[2]]+1]],30sbox[[t2[[3]]+1]],sbox[[t2[[4]]+1]]};31t4=t3[[1]]*2^24+t3[[2]]*2^16+t3[[3]]*2^8+t3[[4]];32t5=IntegerDigits[t4,2,32];33t6=FromDigits[RotateLeft[t5,2],2];34t7=FromDigits[RotateLeft[t5,10],2];35t8=FromDigits[RotateLeft[t5,18],2];36t9=FromDigits[RotateLeft[t5,24],2];37xt[[4]]=BitXor[x[[1]],t4,t6,t7,t8,t9];38x=xt39,{i,1,32}];40x=Reverse[x];41c1=IntegerString[#,16,8]&/@x;42c=ToUpperCase[StringJoin[c1]]43]SM4密码的解密算法与加密算法完全相同,只是轮密钥以相反的顺序输入。因此,上述解密函数sm4de与加密函数sm4en相同,除了第3行代码,即输入的轮密钥以相反的顺序。对于解密函数sm4de而言,输入为密钥和密文(这里用p表示),输出为解密后的文本(这里用c表示)。解密函数sm4de的含义参考sm4en。所得结果如图5-1所示图5-1SM4算法加密解密结果(2)CBC模式下的中文长文本SM4加密与解密1sm4entxt[k_,p_]:=Module[2{key=k,p1=p,p2,p3,p4,p5,p6,p7,p8,p9,p10,len,3c1,c2,c3,c4,c5,c6,t1,t2,t3,t4,t5,t6,t7},4p2=Characters[p1];5p3=ToCharacterCode/@p2;6p4=Flatten[p3];7p5=IntegerDigits[#,16,4]&/@p4;8p6=Flatten[p5];9p7=PadRight[p6,Length[p6]+32-Mod[Length[p6],32]];10p8=Partition[p7,32];11p9=IntegerString[#,16]&/@p8;12p10=ToUpperCase[StringJoin/@p9];13len=Length[p10];14c1=Table[0,len];15Table[16If[i==1,c1[[i]]=sm4en[key,p10[[i]]],17t1=StringPartition[p10[[i]],1];t2=FromDigits[#,16]&/@t1;18t3=StringPartition[c1[[i-1]],1];19t4=FromDigits[#,16]&/@t3;20t5=BitXor[t2,t4];21t6=ToUpperCase[IntegerString[#,16]&/@t5];22t7=StringJoin[t6];23c1[[i]]=sm4en[key,t7]],24{i,1,len}];25c2=StringPartition[#,1]&/@c1;26c3=Flatten[c2];27c4=Partition[c3,4];28c5=StringJoin[#]&/@c4;29c6=FromDigits[#,16]&/@c530]在上述代码中,sm4entxt函数的输入为密钥k和明文p。第2~3行初始化key和明文p1以及一些局部变量。第4行将字符串p1分成字符列表p2。第5行将p2的各个字符转化为编码列表p3(此时的p3为三层嵌套列表)。第6行压平p3得到单层列表p4。第7行将p4的每个元素它对应的4个16进制数表示,即每个元素用一个子列表表示,这个子列表包含4个16进制数,若将这4个数组合在一起即得到这个元素。请注意,这里将每个元素用长度为4的16进制数表示,说明每个元素的取值在0~65535间,因此,这个程序可以处理汉字编码。但是,如果只处理英文字符的加密,这里第7行可以改为“p5=IntegerDigits[#,16,2]&/@p4;”,因为每个英文字符至多1个字节(2个十六进制数)。如果这里做了改变,请对应地修改下面的解密函数sm4detxt中的第4行,这一行改为“c2=IntegerString[#,16,2]&/@c1;”。做这些修改工作后,sm4entxt和sm4detxt将只能加密和解密英文文本,例如,对于习题2中文本的加密与解密。第8行将第7行得到的二层嵌套列表p5压平为单层列表p6;第9行向p6的尾部填充0使其长度为32的整数倍,填充后的列表为p7。第10行将p7分隔成32个元素一组的二层嵌套列表p8。第11行将p8的每个元素转化为字符。第12行将p9的每个长度为32的子列表合并成一个字符串,这个字符串长度为128位,并将小写字符转化为大写字符,然后将结果赋给p10。这样,p10中的每个元素的长度均为128位,即每个元素为一个明文分组。第13行得到p10的长度,赋给len,len就是p10中包含的明文分组的个数。第14行得到长度为len的全0列表。第15~24行为加密过程,局部变量i从1按步长1至len,循环len次。每次循环中:首先判断i是否为1,如果i等于1,则调用sm4en函数加密p10[[1]],得到c1[[1]](第16行);如果i不为1(大于1),则执行第17~20行:第17行将字符串p10[i]分成单个字符的列表t1,然后,将t1转化为整数列表t2;第18行将字符串c1[i-1]分成单个字符的列表t3;第19行将t3转化为整数列表t4;第20行将t2与t4异或,得到t5;第21行将t5转化为字符列表t6;第22行将t6合并为字符串t7。上述操作本质上实现了式(7.12)中的pi⊕ci-1。由于sm4en要求输入的明文为字符串,所以第20~21行将异或结果转化为字符串t7。最后,第23行调用sm4en加密t7得到c1[[i]]。上述循环结束后,得到密文c1,此时的c1为字符串列表。第25行将c1转化为字符列表c2;第26行将c2压平为单层列表c3;第27行将c3分裂成4个字符一组的双层列表c4;第28行将c4的每个子列表合并为一个字符串,得到一个字符串列表c5。第29行将c5转化为整数列表c6,此时每个整数对应着一个汉字编码。由于有些编码没有对应的汉字,所以,加密后的密文结果以编码的形式呈现出来。SM4解密文本函数是上述SM4加密文本函数的逆过程,SM4解密文本的函数sm4detxt如下所示:1sm4detxt[k_,c_]:=Module[2{key=k,c1=c,c2,c3,c4,len,t1,t2,t3,t4,t5,t6,t7,t8,3p1,p2,p3,p4,p5,p6,p7},4c2=IntegerString[#,16,4]&/@c1;5c3=Partition[c2,8];6c4=ToUpperCase[StringJoin/@c3];7len=Length[c4];8p1=Table[0,len];9Table[10If[i==1,p1[[i]]=sm4de[key,c4[[i]]],11t3=sm4de[key,c4[[i]]];12t1=StringPartition[c4[[i-1]],1];13t2=FromDigits[#,16]&/@t1;14t4=StringPartition[t3,1];t5=FromDigits[#,16]&/@t4;15t6=BitXor[t2,t5];16t7=ToUpperCase[IntegerString[#,16]&/@t6];17t8=StringJoin[t7];18p1[[i]]=t8],19{i,1,len}];20p2=StringPartition[#,1]&/@p1;21p3=Flatten[p2];22p4=Partition[p3,4];23p5=StringJoin[#]&/@p4;24p6=FromDigits[#,16]&/@p5;25p7=FromCharacterCode[{p6}]26]在上述解密函数sm4detxt的代码中,输入为密钥k和密文c,需要注意的是,这里的密文以编码的形式输入,所以不需要进行汉字转码处理。第2~3行初始化密钥key=k和密文c1=c以及其他的一些模块中使用的局部变量。第4行将编码形式的c1中的每个元素(0~65535间的整数)转化为十六进制形式的字符串,得到一个字符串列表c2。第5行将c2分裂分8个字符串一组的二层嵌套列表c3。第6行先将c3的每个子列表合并为一个字符串,得到一个字符串列表,再将列表中的小写字符转化为大写字符,结果列表记为c4。这样,c4中的每个元素均为128比特的字符串,每个字符串就是一个密文分组。第7行得到c4的长度,即得到密文分组的个数。第8行得到长度为len的全0列表p1,用于保存解密后的文本。第9行至第19行为解密操作,由Table函数实现。在Table函数,局部变量i从1按步长1递增到len,每步执行如下的操作:先判断变量i是否为1,如果i的值为1,则调用sm4de函数解密c4[[1]],得到解密的文本,赋给p1[[1]](第10行)。如果i的值不为1(大于1),则执行第11~18行,即实现式(7.14)的算法:第11行调用sm4de函数解密c4[[i]],得到的解密文本赋给t3;第12行将c4[[i-1]]分裂为单个字符的列表t1;第13行将t1转化为整数列表t2;第14行将字符串t3转化为单个字符的列表t4,并将t4转化为整数列表t5;第15行将t2和t5异或,结果赋给t6;第16行将t6转化为十六进制的字符串列表t7;第17行将t7合并为一个字符串t8;第18行将t8赋给p1[[i]]。这里的t8即为每步中解密后的文本。上述的p1为总的解密后的文本,以字符串列表的形式存储。第20行将p1中的每个字符串元素分裂为字符列表的形式,保存在p2中。第21行将p2压平为单层列表p3。第22行将p3分裂为每4个字符一组的二层嵌套列表,保存在p4中。第23行将p4中的每个子列表(每个子列表包含4个字符)合并一个字符串,得到一个字符串列表,保存在p5中。第24行将p5中的每个字符串转化为一个整数,得到一个整数列表p6。第25行将{p6}转化为汉字字符串,保存在p7中,同时,p7作为模块的输出。如图5-2所示为SM4算法CBC模式下中文长文本加解密结果。图5-2SM4算法CBC模式中文长文本加解密结果(3)SM4图像加解密SM4图像加密算法与CBC中文长文本加密算法类似,不过将加密前的中文字符转码变成图像信息获取;SM4图像加密函数sm4enimg代码如下所示:1sm4enimg[k_,p_]:=2Module[{key=k,p1=p,p2,p3,p4,p5,p6,p7,p8,p9,p10,len,3c1,c2,c3,c4,c5,c6,c7,t1,t2,t3,t4,t5,t6,t7},4p2=ImageData[p1,"Byte"];5p3=Flatten[p2];6p4=IntegerDigits[#,16,2]&/@p3;7p5=Flatten[p4];8p6=PadRight[p5,Length[p5]+32-Mod[Length[p5],32]];9p7=Partition[p6,32];10p8=IntegerString[#,16]&/@p7;11p9=ToUpperCase[StringJoin/@p8];12len=Length[p9];13c1=Table[0,len];14Table[If[i==1,c1[[i]]=sm4en[key,p9[[i]]],15t1=StringPartition[p9[[i]],1];t2=FromDigits[#,16]&/@t1;16t3=StringPartition[c1[[i-1]],1]

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论