完整的AES分组与文件的加解密功能程序实现

[在此处输入文章标题]

完整的AES分组与文件的加解密功能程序实现

 

1 前言

本报告论述在论述AES加密/解密算法理论的基础上,设计一个AES加密/解密软件系统。AES,密码学中的高级加密标准(Advanced Encryption Standard,AES),又称 Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。AES在软体及硬件上都能快速地加解密,相对来说较易于实作,且只需要很少的记忆体。作为一个新的加密标准,目前正被部署应用到更广大的范围。AES具有以下可变密钥长为128bit、192bit、256bit三种,可变分组长为 128bit、192bit、256bit,同时它的强度高,能够抗所有已知的攻击。

2 程序实现要点(编程语言与开发环境、构件实现核心方法与程序设计技巧)

编写语言:java

开发环境:windows 8,MyEclipse,

用MyEclipse编写,生产jar文件,进而通过exe4j转化为exe程序,该可以在装有 windows 系统的计算机上使用。

3 程序实算展示

3.1 字节替换

SubWord()变换是一个基于S盒的非线性置换,它用于将输入或中间态的每一个字节通过一个简单的查表操作,将其映射为另一个字节。映射方法是把输入字节的高四位作为S盒的行值,低四位作为列值,然后取出S盒中对应的行和列的元素作为输出。

public     void  SubWord(char []A)//字节替代,用于密钥扩展;

{

for(int i=0;i<4;i++)

A[i]=S_BOX[A[i]];

}

//    S盒置换

public static char [] S_BOX = {

99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,

118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,

114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,

49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,

9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,

0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,

170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,

143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,

95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,

34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,

36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,

78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,

180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,         246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,

148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,

66,104,65,153,45,15,176,84,187,22,};

3.2行移位

ShiftRows()完成基于行的循环移位操作,变换方法是第0行不动,第一行循环左移一个字节,第二位循环左移两个字节,第三行循环左移三个字节。

/*

* 行移位

*/

public     void  ShiftRows(char []state, int Nb,JTextArea showProcess)

{

String STR="";

String output="";

char[]  t = new char [8];

for( int r=0;r<4;r++)

{

for(int c=0;c<Nb;c++)t[c]= state[Nb*r+(r+c)%Nb];

for(int c=0;c<Nb;c++){

state[Nb*r+c]=t[c];

STR+=state[Nb*r+c];

}

}

for (int i=0;i<STR.length();i++)

{

int ch = (int)STR.charAt(i);

String s4 = Integer.toHexString(ch);

output = output+"  0x" + s4;

}   //0x表示十六进制

showProcess.append("\n经过行移位后变为:"+output);

}

3.3列混合

MixColumns()实现逐列混合,方法是s’(x)=c(x)*s(x)mod(x^4+1)

/*

* 列混合

*/

public     void  MixColumns(char[]state, int Nb,JTextArea showProcess)

{

String STR="";

String output="";

int [] t = new int[4];

for( int c=0;c<Nb;c++)

{

for(int r=0;r<4;r++)t[r] = state[Nb*r+c];

for(int r=0;r<4;r++)

{

state[Nb*r+c] = (char)(Ffmul(0x02,t[r])^Ffmul(0x03,t[(r+1)%4])

^t[(r+2)%4]^t[(r+3)%4]);

STR+=state[Nb*r+c];

}

}

for (int i=0;i<STR.length();i++)

{

int ch = (int)STR.charAt(i);

String s4 = Integer.toHexString(ch);

output = output+"  0x" + s4;

}   //0x表示十六进制

showProcess.append("\n经过列混合后变为"+output);

}

public     int Ffmul(int A, int B)

{

//查对数表;

if(A==0||B==0)return 0;

A = Log[A];

B = Log[B];

A =(A+B)%0xff;

//查反对数表;

A = Log_1[A];

return A;

}

3.4轮密钥加

AddRoundKey()用于将输入或中间态S的每一列与一个密钥字ki进行按位异或,每一个轮密钥由Nb个字组成。

/*

* 轮密钥加

*/

public     void  AddRoundKey(char[]state,  int Nb,int round,JTextArea showProcess)

{

String Kkey="";

String STR="";

String output="";

for(int c=0;c<Nb;c++,round++)

for(int r=0;r<4;r++){

state[r*Nb+c] = (char)(state[r*Nb+c]^w[round*4+r]);

Kkey+=w[round*4+r];

STR+=state[Nb*r+c];

}

for (int i=0;i<Kkey.length();i++)

{

int ch = (int)Kkey.charAt(i);

String s4 = Integer.toHexString(ch);

output = output+"  0x" + s4;

}   //0x表示十六进制

showProcess.append(output);

for (int i=0;i<STR.length();i++)

{

int ch = (int)STR.charAt(i);

String s4 = Integer.toHexString(ch);

output = output+"  0x" + s4;

}   //0x表示十六进制

showProcess.append("\n经过轮密钥加后变为:"+output);

}

3.5密钥扩展

通过生成器产生Nr+1个轮密钥,每个轮密钥由Nb个字组成,共有Nb(Nr+1)个字。在加密过程中,需要Nr+1个轮密钥,需要构造4(Nr+1)个32位字。首先将输入的4个字节直接复制到扩展密钥数组的前4个字中,然后每次用4个字填充扩展密钥数余下的部分。

/*

* 密钥扩展

*/

public     byte[]  Transform(char[]state, int Nb,int Nr,JTextArea showProcess)

{

int round=1;

int l=0;//计算轮数;

showProcess.append("\n初始密钥为:");

AddRoundKey(state,Nb,0,showProcess);

for(;round<Nr;round++)

{

l++;

SubChar(state,Nb,showProcess);//字节代替

ShiftRows(state,Nb,showProcess);//行移位

MixColumns(state,Nb,showProcess);//列混合

showProcess.append("\n第"+l+"轮子密钥为:");

AddRoundKey(state,Nb,round*Nb,showProcess);//轮密钥加

}

SubChar(state,Nb,showProcess);

ShiftRows(state,Nb,showProcess);

AddRoundKey(state,Nb,round*Nb,showProcess);

return CharToByte(state);

}

public     byte[] ReTransform(char []state, int Nb,int Nr,JTextArea showProcess)

{

int l=0;

showProcess.append("\n初始密钥为:");

AddRoundKey(state, Nb,Nr*Nb,showProcess);

for(int round=Nr-1;round>=1;round--)

{

l++;

InvShiftRows(state,Nb,showProcess);

InvSubint(state,Nb,showProcess);

showProcess.append("\n初始密钥为:");

AddRoundKey(state,Nb,round*Nb,showProcess);

showProcess.append("\n第"+l+"轮子密钥为:");

InvMixColumns(state,Nb,showProcess);

}

InvShiftRows(state,Nb,showProcess);

InvSubint(state,Nb,showProcess);

AddRoundKey(state,Nb,0,showProcess);

return CharToByte(state);

}

3.6逆字节替换

与字节代替类似,逆字节代替基于逆S盒实现。

/*

* 逆字节替换

*/

public    void  InvSubint(char []state, int Nb,JTextArea showProcess)

{

for(int i=0;i<4*Nb;i++)

state[i] = S_BOX_1[state[i]%256];

}

3.7逆行移位

与行移位相反,逆行移位将态state的后三行按相反的方向进行移位操作,即第0行保持不变,第1行循环向右移一个字节,第2行循环向右移动两个字节,第3行循环向右移动三个字节。

/*

* 逆行移位

*/

public    void  InvShiftRows(char[]state, int Nb,JTextArea showProcess)

{

char [] t = new char[8];

for( int r=0;r<4;r++)

{

for(int c=0;c<Nb;c++)

t[(c+r)%Nb] = state[r*Nb+c];

for(int c=0;c<Nb;c++)

state[r*Nb+c]=t[c];

}

}

3.8逆列混合

逆列混淆的处理办法与InvMixColumns()类似,每一列都通过与一个固定的多项式d(x)相乘进行交换。

/*

* 逆列混合

*/

public    void  InvMixColumns(char []state, int Nb,JTextArea showProcess)

{

char  []t = new char[4];

for( int c=0;c<Nb;c++)

{

for(int r=0;r<4;r++)t[r] = state[Nb*r+c];

for(int r=0;r<4;r++)

{

state[Nb*r+c] = (char)(Ffmul(0x0e,t[r])^Ffmul(0x0b,t[(r+1)%4])

^Ffmul(0x0d,t[(r+2)%4])^Ffmul(0x09,t[(r+3)%4]));

}

}

}

3.9 加密

加密部分分了两种情况,一种是自动检查加密程序的正确性,之前在程序里给明文和密钥赋上初值,运行程序检验结果是否正确;另一种是用户手动输入32位的十六进制数,进行加密,我是把每一具体项模块化,将功能在每个具体模块中实现,只需要直接调用,视觉效果强,一目了然。

下面是实现加密功能一些关键代码

/*

* 加密

*/

public long AES_Encrypt(String OpenPath,String SavePath,String m_Key,int Nb,int Nk,JTextArea T)

throws IOException

{

showProcess=T;

showProcess.append("\n加密文件...");

//以二进制读的方式打开要加密的文件;

//以二进制写的方式打开保存密文的文件;

FileInputStream fp1 = new FileInputStream(OpenPath);

FileOutputStream fp2 = new FileOutputStream(SavePath,true);

int Length = fp1.available();//得到要加密的文件的长度,单位bit;

if(Length==0)return 0;

int  leave = Length%(4*Nb);                         //求剩余的字块的字节数;

long rounds = Length/(4*Nb);                        //得到整块的加密轮数;

if(leave!=0)rounds++;

long copy_rounds = rounds;//rounds可以变化不影响copy_rounds的值

showProcess.append("\n正在加密"+rounds+"个明文组");

byte[] state = new byte[4*8]; //作为加密时存放要加密的明文块,字节类型数组;

byte[] copy = new byte[4*8];               //用来进行短块处理时的缓存区;

int Nr=GetRounds(Nb,Nk);      //得到加密的轮数,Nb为密钥矩阵的列数;

KeyExpansion(m_Key,Nb,Nk,Nr); //生成各轮子密钥;

if(copy_rounds==1&&rounds==1)

{

if(leave==0) fp1.read(state,0,4*Nb);//明文的长度恰好等于分组长度;

else

{

fp1.read(state,0,leave);//明文的长度小于八个字符,每个字符一字节;

for(int i=leave;i<4*Nb;i++)

state[i]=0;             //后面用空格补齐;

}

state = Transform(ByteToChar(state),Nb,Nr,showProcess);                   //加密变换;

fp2.write(state,0,4*Nb);//将加密后的密文块写入目标文件;

rounds--;

}

else if(copy_rounds>1&&leave!=0)//如果明文的长度大于分组长度且字符数不是分组长度的整数倍

{                               //时,需要进行短块处理;

fp1.read(state,0,4*Nb);

state = Transform(ByteToChar(state),Nb,Nr,showProcess);//先加密最前面的一块;

fp2.write(state,0,leave);//将余数个数那么多的密文前面部分字符存入文件;

int j=0;

for(int i=leave;i<4*Nb;i++)

copy[j++]=state[i];//将最先加密的密文的后部分放在短块前面,长度为分组长度减去leave;

fp1.read(copy,j,leave);//将剩余个数那么多的明文放在后面(是第二组明文块中的明文),组成一组完整加密明文块;

copy = Transform(ByteToChar(copy),Nb,Nr,showProcess);

fp2.write(copy,0,4*Nb);

rounds-=2;//这就加密了2组了,实质是一组多;

}

while(rounds>0)//以下处理的明文是分组的整数倍的情况;

{

fp1.read(state,0,4*Nb);

state = Transform(ByteToChar(state),Nb,Nr,showProcess);

fp2.write(state,0,4*Nb);

rounds--;

}

fp1.close();//关闭源文件和目标文件;

fp2.close();

return ((copy_rounds-1)*4*Nb+leave);//返回文件长度;

}

3.10 解密

AES解密我也是分成了两个部分,第一部分是在程序中对密文和密钥赋初值,通过与标准对照检查解密过程的正确性;第二部分是用户手动输入密文和密钥,程序对其进行解密,得到最后的明文。

解密过程基本如下:

1)获取输入的明文和密钥

2)通过密钥扩展过程获取各轮密钥

3)轮密钥加变换过程

4)逆行移位

5)逆字节替代

6)轮密钥加变换

7)逆列混淆

4—7步共9次循环,最后一轮实现4—6步,完成解密过程。

主要代码如下:

public     long AES_DeEncrypt(String OpenPath,String SavePath,String  m_Key, int Nb, int Nk,JTextArea showProcess)

throws IOException

{

showProcess.append("\n解密文件...");

//以二进制读的方式打开要解密密的文件;

//以二进制写的方式打开保存解开的密文文件;

FileInputStream fp1= new FileInputStream(OpenPath);

FileOutputStream fp2= new FileOutputStream(SavePath,true);

int Length = fp1.available();//得到要解密的文件的长度;

if(Length==0)return 0;

int  leave=Length%(4*Nb);//求剩余的字块的字节数;

long rounds=Length/(4*Nb);//得到整块的解密轮数;

if(leave!=0)rounds++;

long copy_rounds=rounds;

showProcess.append("\n正在解密"+rounds+"个密文组");

byte []state = new byte[4*8]; //解密时存放密文块;

int Nr = GetRounds(Nb,Nk);      //得到解密时循环轮数;

KeyExpansion(m_Key,Nb,Nk,Nr); //生成各轮子密钥

byte[] copy = new byte[32];

if(leave!=0)//需要进行短块处理

{

fp1.read(copy,0,leave);//先把余数个密文字符保存进数组;

fp1.read(state,0,4*Nb);//读取紧接着的下一个密文块;

state = ReTransform(ByteToChar(state),Nb,Nr,showProcess);          //解密;

int j=0;

for(int i=leave;i<4*Nb;i++)        //把解密后的明文前部分和前面的余数个合在一起组成一块,

copy[i]=state[j++];            //一起解密;

copy = ReTransform(ByteToChar(copy),Nb,Nr,showProcess);

//将解密后的明文写入目标文件;

fp2.write(copy,0,4*Nb);

fp2.write(state,j,leave);//将余数个明文写入目标文件;

rounds-=2;               //已经完成了两轮解密所以减二;

}

while(rounds>0)//对后面是分组长度的整数倍的密文块解密;

{

fp1.read(state,0,4*Nb);//读取密文块;

copy = ReTransform(ByteToChar(state),Nb,Nr,showProcess);   //解密变换;

fp2.write(copy,0,4*Nb);//将解密后的明文写入目标文件;

rounds--;                           //轮数减一;

}

fp1.close();//关闭源文件和目标文件;

fp2.close();

return ((copy_rounds-1)*4*Nb+leave);//返回文件长度

}

3.11 效果截图

图1 软件软件效果图

图2 加密前的源文件数据:

图3 加密过程显示结果图

图4 加密过程显示结果图

图 5 加密后效果图:

4 结语

经过这次《信息安全技术》的课程学习和项目实践设计,我个人得到了不少的收获,一方面加深了我对课本理论的认识,另一方面也提高了实践操作能力。

我的此次课程作业中我主要关于编写一个加密解密程序,这也使得我更加扎实的掌握了有关于信息安全密码学的相关方面的知识。在设计过程中虽然遇到了一些困难,但经过一次又一次的思考,一遍又一遍的检查终于找出了问题所在,也暴露出了前期我在这方面的知识欠缺和经验不足。实践出真知,通过亲自动手编写开发,使我们掌握的知识得以实践。

在课程作业过程中,我们不断发现错误,不断改正,不断领悟,不断获取。在设计过程中遇到了很多问题,最后在不懈的努力下,终于迎刃而解。在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成想做的事,才能在今后的道路上劈荆斩棘,而不是知难而退,那样永远不可能收获成功,收获喜悦,也永远不可能得到社会及他人对你的认可!

个人认为,在这本次的的课程作业中,不仅培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。更重要的是,在课程作业过程中,我们学会了很多学习的方法。而这是日后最实用的,真的是受益匪浅。要面对社会的挑战,只有不断的学习、实践,再学习、再实践。这对于我们的将来也有很大的帮助。以后,不管有多苦,我想我们都能变苦为乐,找寻有趣的事情,发现其中珍贵的事情。回顾起此课程作业,从理论到实践,可以说得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程作业使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。

总之,认真对待每一个学习的机会,珍惜过程中的每一分一秒,学到最多的知识和方法,锻炼自己的能力,这个是我在本次信息安全技术课程作业中学到的最重要的、受用终身的知识!

可以下载原来文件:http://download.csdn.net/detail/zhoujn90/8369289

时间: 2024-10-14 00:39:46

完整的AES分组与文件的加解密功能程序实现的相关文章

Android jni aes加解密,实现文件的加解密,具体实现可以自行修改,上面的代码为简单介绍,下面的是JNI端实现文件加解密,可以修改为字符串加解密

#include "aes.h" #include "modes.h" #include "e_os2.h" #include "aes_locl.h" #include "opensslconf.h" AES_KEY aes; //aes cbc模式加解密用到的向量 unsigned char iv[AES_BLOCK_SIZE]; for (i = 0; i < AES_BLOCK_SIZE; i

文件透明加解密系统项目方案——(1)需求分析

最近发现MDT推出去的系统的有不同问题,其问题就不说了,主要是策略权限被域继承了.比如我们手动安装的很多东东都是未配置壮态,推的就默认为安全壮态了,今天细找了一下,原来把这个关了就可以了. 文件透明加解密系统项目方案--(1)需求分析

微信消息体签名及加解密功能详细解析以及.net实现

原文:微信消息体签名及加解密功能详细解析以及.net实现 前言 微信消息体签名及加密功能已上线,明文传输确实存在安全风险,鉴于微信的用户范围使用之广泛,必定会成为众矢之的.所以大家还是尽快接入安全模式为好.仔细阅读官方接入指南,发现这次安全升级只是涉及到用户在微信对话窗口中与公众好消息交互,所以此次升级还是比较简单的.下面为大家一一道来. 一.功能解析 微信消息体签名及加密功能已上线,出于安全考虑,强烈建议您尽快接入消息加密功能,消除安全风险.详见公告.公众平台接口调试工具已经全面支持消息体加密

Spring Cloud Config 配置中心 自动加解密功能

使用  jasypt-spring-boot-starter  进行加解密功能. 整个流程说明: 配置一个 spring cloud config server ,将要使用的配置文件存放到github上,然后从这个配置源拿配置. 我们使用 jasypt 进行自动加解密,将需要加密的数据,通过jasypt进行加密,然后将该内容放入 github.如下图: 使用 ENC() 将加密后的原文包裹,这样spring cloud config client 客户端拿到这个串之后,会自动解密,拿到原文. 下

SpringBoot中如何灵活的实现接口数据的加解密功能?

数据是企业的第四张名片,企业级开发中少不了数据的加密传输,所以本文介绍下SpringBoot中接口数据加密.解密的方式. 本文目录 一.加密方案介绍二.实现原理三.实战四.测试五.踩到的坑 一.加密方案介绍 对接口的加密解密操作主要有下面两种方式: 自定义消息转换器 优势:仅需实现接口,配置简单.劣势:仅能对同一类型的MediaType进行加解密操作,不灵活. 使用spring提供的接口RequestBodyAdvice和ResponseBodyAdvice 优势:可以按照请求的Referrer

C# 文件压缩加解密

1.这种方式也可以做到对文件的加密压缩,解密解压缩,只是在压缩和解压缩时会出现压缩窗口 1.1加密压缩 strzipPath:压缩包路径 strtxtPath:待压缩的文件路径 password:加密密码 public bool Zip(string strzipPath, string strtxtPath,string password) { try { System.Diagnostics.Process Process1 = new System.Diagnostics.Process(

ios开发不能不知的动态修复bug补丁第三方库JSPatch 使用学习:JSPatch导入、和使用、.js文件传输加解密

JSPatch ios开发面临审核周期长,修复bug延迟等让人无奈的问题,所以,热修复的产生成为必然. ios上线APP产生bug,需要及时修复,如何修复: 我整理了jspatch的使用说明,并建立一个简单demo供他人使用和学习,此博客不做详细介绍,具体如何使用附上代码地址: 代码下载地址: https://github.com/niexiaobo/JSPatchUse ##### demo.js里添加代码:1.重写crashBtnClick方法 2.跳转新建的JPTableViewContr

AES加解密算法Qt实现

[声明] (1) 本文源码 在一位未署名网友源码基础上,利用Qt编程,实现了AES加解密算法,并添加了文件加解密功能.在此表示感谢!该源码仅供学习交流,请勿用于商业目的. (2) 图片及描述 除图1外,图片及部分解析来自http://zh.wikipedia.org/wiki/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86.图1为个人劳动成果,请勿盗用此图. [简介] AES(Advanced Encryption Standard,

CryptoGUI | 文件加解密

分类: 杂类工具    版本: 0.0.3    发布日期: 2015-03-31 根据 crypto 强加密命令行工具制作的可视化版本,可快速进行任意文件的加解密操作,提供丰富的加解密选项以适应多种不同需求:CryptoGui 在 crypto 的基础上进行了人性化定制,使用更方便. 功能简介 支持当今绝大部分对称强加密算法 可定制的密钥长度,从最低32位到最高的448位.信息安全强度由用户自由选择. 算法库基于优秀的 Cryptopp 库封装,已通过FIPS 140-2美国国家信息处理标准一