java aes算法_AES算法的JAVA实现

package myLib.AES;

/**

* This class is designed to encrypt file using AES.

* @author ZhuTao 2006.5.5.HUST

* Email:greenkugua@sina.com.cn

* QQ:307356132

* @version 1.0

*/

/**

* 可以把它们做成自己的库函数,方便以后使用。

*/

public class AESMap {

public static char []  key;

public static char []  w;//用来存放扩展后的子密钥;

public static char []Log =  {

0,0,25,1,50,2,26,0xc6,75,199,27,104,51,238,223,3,100,4,

224,14,52,141,129,239,76,113,8,200,248,105,28,193,125,194,29,

181,249,185,39,106,77,228,166,114,154,201,9,120,101,47,138,

5,33,15,225,36,18,240,130,69,53,147,218,142,150,143,219,189,

54,208,206,148,19,92,210,241,64,70,131,56,102,221,253,48,

191,6,139,98,179,37,226,152,34,136,145,16,126,110,72,195,163,

182,30,66,58,107,40,84,250,133,61,186,43,121,10,21,155,159,

94,202,78,212,172,229,243,115,167,87,175,88,168,80,244,234,

214,116,79,174,233,213,231,230,173,232,44,215,117,122,235,

22,11,245,89,203,95,176,156,169,81,160,127,12,246,111,23,

196,73,236,216,67,31,45,164,118,123,183,204,187,62,90,251,96,

177,134,59,82,161,108,170,85,41,157,151,178,135,144,97,190,

220,252,188,149,207,205,55,63,91,209,83,57,132,60,65,162,

109,71,20,42,158,93,86,242,211,171,68,17,146,217,35,32,46,137,

180,124,184,38,119,153,227,165,103,74,237,222,197,49,254,

24,13,99,140,128,192,247,112,7,};

public static char[] Log_1 = {

1,3,5,15,17,51,85,255,26,46,114,150,161,248,19,53,95,225,

56,72,216,115,149,164,247,2,6,10,30,34,102,170,229,52,92,

228,55,89,235,38,106,190,217,112,144,171,230,49,83,245,4,12,

20,60,68,204,79,209,104,184,211,110,178,205,76,212,103,169,

224,59,77,215,98,166,241,8,24,40,120,136,131,158,185,208,

107,189,220,127,129,152,179,206,73,219,118,154,181,196,87,249,

16,48,80,240,11,29,39,105,187,214,97,163,254,25,43,125,135,

146,173,236,47,113,147,174,233,32,96,160,251,22,58,78,210,

109,183,194,93,231,50,86,250,21,63,65,195,94,226,61,71,201,

64,192,91,237,44,116,156,191,218,117,159,186,213,100,172,

239,42,126,130,157,188,223,122,142,137,128,155,182,193,88,232,

35,101,175,234,37,111,177,200,67,197,84,252,31,33,99,165,

244,7,9,27,45,119,153,176,203,70,202,69,207,74,222,121,139,

134,145,168,227,62,66,198,81,243,14,18,54,90,238,41,123,141,

140,143,138,133,148,167,242,13,23,57,75,221,124,132,151,162,

253,28,36,108,180,199,82,246,1};

//    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,};

//    S盒逆置换;

public  char [] S_BOX_1={

82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,

124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,

84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,8,

46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,114,

248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,108,

112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,144,

216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,208,44,

30,143,202,63,15,2,193,175,189,3,1,19,138,107,58,145,17,65,

79,103,220,234,151,242,207,206,240,180,230,115,150,172,116,

34,231,173,53,133,226,249,55,232,28,117,223,110,71,241,26,

113,29,41,197,137,111,183,98,14,170,24,190,27,252,86,62,75,

198,210,121,32,154,219,192,254,120,205,90,244,31,221,168,51,

136,7,199,49,177,18,16,89,39,128,236,95,96,81,127,169,25,181,

74,13,45,229,122,159,147,201,156,239,160,224,59,77,174,42,

245,176,200,235,187,60,131,83,153,97,23,43,4,126,186,119,214,

38,225,105,20,99,85,33,12,125,};

public static  char []Rcon={

0x01,0x00,0x00,0x00,

0x02,0x00,0x00,0x00,

0x04,0x00,0x00,0x00,

0x08,0x00,0x00,0x00,

0x10,0x00,0x00,0x00,

0x20,0x00,0x00,0x00,

0x40,0x00,0x00,0x00,

0x80,0x00,0x00,0x00,

0x1b,0x00,0x00,0x00,

0x36,0x00,0x00,0x00};

public     AESMap()

{

key = new char[4*8];

w = new char[8*15*4];//用来存放扩展后的子密钥;

}

}

package myLib.AES;

import java.io.IOException;

import java.io.FileOutputStream;

import java.io.FileInputStream;/**

* This class is designed to encrypt file using AES.

* @author ZhuTao 2006.5.5.HUST

* Email:greenkugua@sina.com.cn

* QQ:307356132

* @version 1.0

*/

/**

*

* 把它们做成自己的库函数,方便以后使用。

*/

public class AES extends AESMap {

/**

* This method is used to encrypt data with AES.

* @param OpenPath the path of the file which you want to encrypt.

* @param SavePath the path to save the encrypted file

* @param m_Key the encrypt key of user.

* @param Nb the length of file blocks(32bits)

* @param Nk the length of key.

* @return the length of data.(bytes)

* @throws IOException

功能:    AES加密

入口参数:m_Key是用户加密密钥;

fp1是要加密的文件指针;

fp2是加密后保存密文的文件指针;

Nb是加密时明文的分组长度(以32bit为单位);

Nk是密钥的长度(以32bit为单位);

///

*/

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

throws IOException

{

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

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

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;

byte[] state = new byte[4*8]; //作为加密时存放要加密的明文块;

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

int Nr=GetRounds(Nb,Nk);      //得到加密的轮数;

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);                   //加密变换;

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);//先加密最前面的一块;

fp2.write(state,0,leave);//仅将余数个字符存入文件,而将后部分密文

//与后面的明文合在一起加密;

int j=0;

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

copy[j++]=state[i];

fp1.read(copy,j,leave);

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

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

rounds-=2;

}

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

{

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

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

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

rounds--;

}

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

fp2.close();

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

}

/**

* This method is used to de-encrypt cryptograph.

* @param OpenPath the path of cryptograph.

* @param SavePath the path to save the de-encrypted file.

* @param m_Key the key to de-encrypt file.

* @param Nb the length of file blocks(32bits)

* @param Nk the length of key.

* @return the length of data.(bytes)

* @throws IOException

功能:    实现AES的解密

入口参数:m_Key是用户加密密钥;

fp1是要解密的文件指针;

fp2是解密后保存明文的文件指针;

Nb是解密时密文的分组长度(以32bit为单位);

Nk是密钥的长度(以32bit为单位);

注意了,  解密时和加密时的分组长度要一致;

/

*/

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

throws IOException

{

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

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

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;

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);          //解密;

int j=0;

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

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

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

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

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);          //解密变换;

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

rounds--;                           //轮数减一;

}

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

fp2.close();

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

}

/**

* This method is used to shift the data in array A.

* @param A

//

功能:将数组A中的四个字节循环左移一个字节;

//

*/

public     void  RotWord(char[]A)

{

char temp;

temp=A[0];

A[0] = A[1];

A[1] = A[2];

A[2] = A[3];

A[3] = temp;

}

/**

* This method is used to do S-replace durying key-expansion.

* @param A

功能:    密钥扩展的时候进行S盒替换;

入口参数:A是存放四个字节的数组;

*/

public     void  SubWord(char []A)

{

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

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

}

/**

* This method is used to get rounds of  encrypt.

* @param Nb the length of file blocks(32bits)

* @param Nk the length of key.

* @return the rounds of encrypt.

//

功能:返回加密的轮数;

入口参数:Nb以32bit为单位的待加密明文的长度;

Nk是以32bit为单位的初始密钥的长度;

返回值:返回加密轮数(Nr);

*/

public     int  GetRounds(int Nb, int Nk)

{

switch(Nb)

{

case 4:switch(Nk)

{

case 4:return 10;

case 6:return 12;

case 8:return 14;

default:return 0;

}

case 6:switch(Nk)

{

case 4:

case 6:return 12;

case 8:return 14;

default:return 0;

}

case 8:switch(Nk)

{

case 4:

case 6:

case 8:return 14;

default:return 0;

}

default:return 0;

}

}

/**

* This method is used to build sub-keys used in each rounds。

* @param m_Key  the key of user.

* @param Nb the length of file blocks(32bits)

* @param Nk the length of key.

* @param Nr the rounds of encrypt in each block.

入口参数:Nb以32bit为单位的待加密明文的长度;

Nk是以32bit为单位的初始密钥的长度;

Nr是加密的轮数;

m_Key是用户的密钥;

返回值:扩展后的子密钥存放在数组w中;

*/

public     void  KeyExpansion(String m_Key,int Nb, int Nk, int Nr)

{

int i=0;

for(;i<4;i++)

for(int j=0;jkey[i*Nk+j]=m_Key.charAt(i*4+j);

i=0;

while(i{

w[i*4]=key[i*4];

w[i*4+1]=key[i*4+1];

w[i*4+2]=key[i*4+2];

w[i*4+3]=key[i*4+3];

i++;

}

i=Nk;

while(i{

char []temp = new char[4];

temp[0]=w[(i-1)*4+0];temp[1]=w[(i-1)*4+1];

temp[2]=w[(i-1)*4+2];temp[3]=w[(i-1)*4+3];

if((i%Nk)==0)

{

RotWord(temp);

SubWord(temp);

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

temp[j]^=Rcon[((i-1)/Nk)*4+j];//与Rcon异或;

}

else if(Nk==8&&i%Nk==4)

SubWord(temp);

w[i*4+0] = (char)(w[(i-Nk)*4+0]^temp[0]);

w[i*4+1] = (char)(w[(i-Nk)*4+1]^temp[1]);

w[i*4+2] = (char)(w[(i-Nk)*4+2]^temp[2]);

w[i*4+3] = (char)(w[(i-Nk)*4+3]^temp[3]);

i++;

}

}

/**

* This method is used to do S-replace.

* @param state is a array which stored the data block.

* @param Nb the length of data block.

///

功能:    S盒置换

入口参数: Nb为以32bit为单位的明文块的大小;

state为明文块;

*/

public    void  SubChar(char []state,int Nb)

{

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

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

}

/**

* @param state is a array which stored the data block.

* @param Nb the length of data block.

/

功能:    加密对明文块进行移位运算;

入口参数:state是明文块;

Nb是以32比特为单位的明文块的大小;

//

*/

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

{

char[]  t = new char [8];

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

{

for(int c=0;cfor(int c=0;cstate[Nb*r+c]=t[c];

}

}

/**

* This method is used to mix columns.

* @param state is a array which stored the data block.

* @param Nb the length of data block.

//

功能:加密时对明文块进行列混合变换;

入口参数:state是明文块;

Nb是以32比特为单位的明文块的大小;

//

*/

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

{

int [] t = new int[4];

for( int c=0;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]);

}

}

}

/**

* This method is used to get the product of A and B.

* @param A first number.

* @param B second number.

* @return the product of A and B.

/

功能:返回两个域元素A,B的积;

/

*/

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;

}

/**

* This method is used to add round key and data.

* @param state is the array which contains the data.

* @param Nb length of data block(32bits).

* @param round the index of current round.

///

功能:   轮密钥加变换;

入口参数:   state明文块

w为子密钥,Nb为明文块的大小,round为当前加密的轮数;

///

*/

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

{

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

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

}

/**

* This method is used to do exchang durying the proccess of encryption.

* @param state is a array which contains the data to encrypt.

* @param Nb the length of data block(32bits).

* @param Nr the length of user key

* @return the cryptograph.

*/

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

{

int round=1;

AddRoundKey(state,Nb,0);

for(;round{

SubChar(state,Nb);

ShiftRows(state,Nb);

MixColumns(state,Nb);

AddRoundKey(state,Nb,round*Nb);

}

SubChar(state,Nb);

ShiftRows(state,Nb);

AddRoundKey(state,Nb,round*Nb);

return CharToByte(state);

}

/**

* This method is used to do exchang durying the proccess of de-encryption.

* @param state is a array which contains the cryptograph to de-encrypt.

* @param Nb the length of cryptograph block(32bits).

* @param Nr the length of user key

* @return the original text.

*/

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

{

AddRoundKey(state, Nb,Nr*Nb);

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

{

InvShiftRows(state,Nb);

InvSubint(state,Nb);

AddRoundKey(state,Nb,round*Nb);

InvMixColumns(state,Nb);

}

InvShiftRows(state,Nb);

InvSubint(state,Nb);

AddRoundKey(state,Nb,0);

return CharToByte(state);

}

/**

* This method is used to do S-replace durying de-encrypt cryptograph .

* @param state is a array which contains the cryptograph to de-encrypt.

* @param Nb the length of cryptograph block(32bits).

* @param Nr the length of user key

/

功能:解密时的S盒逆置换;

入口参数:state为密文块;

Nb为密文块的大小;

*/

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

{

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

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

}

/**

* This method is used to shift rows durying de-encyrpt cryptograph .

* @param state is a array which contains the cryptograph to de-encrypt.

* @param Nb the length of cryptograph block(32bits).

功能:解密的时候的右移位变换;

入口参数:state为密文块;

Nb为密文块的大小;

*/

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

{

char [] t = new char[8];

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

{

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

for(int c=0;cstate[r*Nb+c]=t[c];

}

}

/**

* This method is used to mix columns durying de-encrypt cyyptograph.

* @param state is a array which contains the cryptograph to de-encrypt.

* @param Nb the length of cryptograph block(32bits).

//

功能:解密时的列混合变换;

入口参数:state为密文块;

Nb为密文块的大小;

//

*/

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

{

char  []t = new char[4];

for( int c=0;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]));

}

}

}

/**

* This method is used to transform a array from byte type to char type.

* @param data a byte type array.

* @return a char type array.

*/

public static char[] ByteToChar(byte[] data)

{

char []A = new char[data.length];

for(int i = 0;iA[i] = (char)data[i];

return A;

}

/**

* This method is used to transform a array from char type to byte type.

* @param data a char type array.

* @return a byte type array.

*/

public static byte[]CharToByte(char[]data)

{

byte[] A = new byte[data.length];

for(int i = 0;iA[i] = (byte)data[i];

return A;

}

}

package myLib.AES;

import java.io.IOException;

public class TestAes {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

AES test = new AES();

System.out.println(test.S_BOX.length);

//(String OpenPath,String SavePath,String m_Key,int Nb,int Nk)

long time = System.currentTimeMillis();

try{

test.AES_Encrypt("G:\\1.mkv","G:\\mkv.txt","1985012619850126",4,4);

test.AES_DeEncrypt("G:\\mkv.txt","G:\\DE.mkv","1985012619850126",4,4);

}catch(IOException e){System.out.println(e);}

long time1 = System.currentTimeMillis();

time = time1-time;

System.out.println(time);

}

}

阅读(691) | 评论(0) | 转发(0) |

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值