熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

AES算法的JAVA實現

2013-11-23 18:44:20  來源: Java核心技術 

  package myLibAES;

  /**

  * This class is designed to encrypt file using AES

  * @author ZhuTao HUST

  * Email:cn

  * QQ:

  * @version

  */

  /**

  * 可以把它們做成自己的庫函數方便以後使用

  */

  public class AESMap {

  public static char []  key;

  public static char []  w;//用來存放擴展後的子密鑰;

  public static char []Log =  {

  xc

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  };

  public static char[] Log_ = {

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  };

  //    S盒置換

  public static char [] S_BOX = {

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  };

  //    S盒逆置換

  public  char [] S_BOX_={

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  };

  public static  char []Rcon={

  xxxx

  xxxx

  xxxx

  xxxx

  xxxx

  xxxx

  xxxx

  xxxx

  xbxxx

  xxxx};

  public     AESMap()

  {

  key = new char[*];

  w = new char[**];//用來存放擴展後的子密鑰;

  }

  }

  package myLibAES;

  import javaioIOException;

  import javaioFileOutputStream;

  import javaioFileInputStream;/**

  * This class is designed to encrypt file using AES

  * @author ZhuTao HUST

  * Email:cn

  * QQ:

  * @version

  */

  /**

  *

  * 把它們做成自己的庫函數方便以後使用

  */

  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(bits)

  * @param Nk the length of key

  * @return the length of data(bytes)

  * @throws IOException

  ////////////////////////////////////////////////////

  功能    AES加密

  入口參數m_Key是用戶加密密鑰

  fp是要加密的文件指針

  fp是加密後保存密文的文件指針

  Nb是加密時明文的分組長度(以bit為單位)

  Nk是密鑰的長度(以bit為單位)

  ///////////////////////////////////////////////////

  */

  public long AES_Encrypt(String OpenPathString SavePathString m_Keyint Nbint Nk)

  throws IOException

  {

  //以二進制讀的方式打開要加密的文件

  //以二進制寫的方式打開保存密文的文件

  FileInputStream fp = new FileInputStream(OpenPath);

  FileOutputStream fp = new FileOutputStream(SavePathtrue);

  int Length = fpavailable();//得到要加密的文件的長度

  if(Length==)return ;

  int  leave = Length%(*Nb);                         //求剩余的字塊的字節數

  long rounds = Length/(*Nb);                        //得到整塊的加密輪數

  if(leave!=)rounds++;

  long copy_rounds = rounds;

  byte[] state = new byte[*]; //作為加密時存放要加密的明文塊

  byte[] copy = new byte[*];               //用來進行短塊處理時的緩存區

  int Nr=GetRounds(NbNk);      //得到加密的輪數

  KeyExpansion(m_KeyNbNkNr); //生成各輪子密鑰

  if(copy_rounds==&&rounds==)

  {

  if(leave==) fpread(state*Nb);//明文的長度恰好等於分組長度

  else

  {

  fpread(stateleave);//明文的長度小於八個字符

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

  state[i]=;             //後面用空格補齊

  }

  state = Transform(ByteToChar(state)NbNr);                   //加密變換

  fpwrite(state*Nb);//將加密後的密文塊寫入目標文件

  rounds;

  }

  else if(copy_rounds>&&leave!=)//如果明文的長度大於分組長度且字符數不是分組長度的整數倍

  {                               //時需要進行短塊處理

  fpread(state*Nb);

  state = Transform(ByteToChar(state)NbNr);//先加密最前面的一塊

  fpwrite(stateleave);//僅將余數個字符存入文件而將後部分密文

  //與後面的明文合在一起加密

  int j=;

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

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

  fpread(copyjleave);

  copy = Transform(ByteToChar(copy)NbNr);

  fpwrite(copy*Nb);

  rounds=;

  }

  while(rounds>)//以下處理的明文是分組的整數倍的情況

  {

  fpread(state*Nb);

  state = Transform(ByteToChar(state)NbNr);

  fpwrite(state*Nb);

  rounds;

  }

  fpclose();//關閉源文件和目標文件

  fpclose();

  return ((copy_rounds)**Nb+leave);//返回文件長度

  }

  /**

  * This method is used to deencrypt cryptograph

  * @param OpenPath the path of cryptograph

  * @param SavePath the path to save the deencrypted file

  * @param m_Key the key to deencrypt file

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

  * @param Nk the length of key

  * @return the length of data(bytes)

  * @throws IOException

  ////////////////////////////////////////////////////////

  功能    實現AES的解密

  入口參數m_Key是用戶加密密鑰

  fp是要解密的文件指針

  fp是解密後保存明文的文件指針

  Nb是解密時密文的分組長度(以bit為單位)

  Nk是密鑰的長度(以bit為單位)

  注意了  解密時和加密時的分組長度要一致

  /////////////////////////////////////////////////////////

  */

  public     long AES_DeEncrypt(String OpenPathString SavePathString  m_Key int Nb int Nk)

  throws IOException

  {

  //以二進制讀的方式打開要加密的文件

  //以二進制寫的方式打開保存密文的文件

  FileInputStream fp= new FileInputStream(OpenPath);

  FileOutputStream fp= new FileOutputStream(SavePathtrue);

  int Length = fpavailable();//得到要加密的文件的長度

  if(Length==)return ;

  int  leave=Length%(*Nb);//求剩余的字塊的字節數

  long rounds=Length/(*Nb);//得到整塊的加密輪數

  if(leave!=)rounds++;

  long copy_rounds=rounds;

  byte []state = new byte[*];              //解密時存放密文塊

  int Nr = GetRounds(NbNk);      //得到解密時循環輪數

  KeyExpansion(m_KeyNbNkNr); //生成各輪子密鑰

  byte[] copy = new byte[];

  if(leave!=)//需要進行短塊處理

  {

  fpread(copyleave);//先把余數個密文字符保存

  fpread(state*Nb);//讀取緊接著的一個密文塊

  state = ReTransform(ByteToChar(state)NbNr);          //解密

  int j=;

  for(int i=leave;i<*Nb;i++)        //把解密後的明文和前面的余數個合在一起組成一塊

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

  copy = ReTransform(ByteToChar(copy)NbNr);

  //將解密後的明文寫入目標文件

  fpwrite(copy*Nb);

  fpwrite(statejleave);//將余數個明文寫入目標文件

  rounds=;                         //已經完成了兩輪解密所以減二

  }

  while(rounds>)//對後面是分組長度的整數倍的密文塊解密

  {

  fpread(state*Nb);//讀取密文塊

  copy = ReTransform(ByteToChar(state)NbNr);          //解密變換

  fpwrite(copy*Nb);//將解密後的明文寫入目標文件

  rounds;                           //輪數減一

  }

  fpclose();//關閉源文件和目標文件

  fpclose();

  return ((copy_rounds)**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[];

  A[] = A[];

  A[] = A[];

  A[] = A[];

  A[] = temp;

  }

  /**

  * This method is used to do Sreplace durying keyexpansion

  * @param A

  ////////////////////////////////////////////////

  功能    密鑰擴展的時候進行S盒替換

  入口參數A是存放四個字節的數組

  ////////////////////////////////////////////////

  */

  public     void  SubWord(char []A)

  {

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

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

  }

  /**

  * This method is used to get rounds of  encrypt

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

  * @param Nk the length of key

  * @return the rounds of encrypt

  //////////////////////////////////////////////////

  功能返回加密的輪數

  入口參數Nb以bit為單位的待加密明文的長度

  Nk是以bit為單位的初始密鑰的長度

  返回值返回加密輪數(Nr)

  ////////////////////////////////////////////////////

  */

  public     int  GetRounds(int Nb int Nk)

  {

  switch(Nb)

  {

  case :switch(Nk)

  {

  case :return ;

  case :return ;

  case :return ;

  default:return ;

  }

  case :switch(Nk)

  {

  case :

  case :return ;

  case :return ;

  default:return ;

  }

  case :switch(Nk)

  {

  case :

  case :

  case :return ;

  default:return ;

  }

  default:return ;

  }

  }

  /**

  * This method is used to build subkeys used in each rounds

  * @param m_Key  the key of user

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

  * @param Nk the length of key

  * @param Nr the rounds of encrypt in each block

  ////////////////////////////////////////////////////

  入口參數Nb以bit為單位的待加密明文的長度

  Nk是以bit為單位的初始密鑰的長度

  Nr是加密的輪數

  m_Key是用戶的密鑰

  返回值擴展後的子密鑰存放在數組w中

  */

  public     void  KeyExpansion(String m_Keyint Nb int Nk int Nr)

  {

  int i=;

  for(;i<;i++)

  for(int j=;j<Nk;j++)

  key[i*Nk+j]=m_KeycharAt(i*+j);

  i=;

  while(i<Nk)

  {

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

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

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

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

  i++;

  }

  i=Nk;

  while(i<Nb*(Nr+))

  {

  char []temp = new char[];

  temp[]=w[(i)*+];temp[]=w[(i)*+];

  temp[]=w[(i)*+];temp[]=w[(i)*+];

  if((i%Nk)==)

  {

  RotWord(temp);

  SubWord(temp);

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

  temp[j]^=Rcon[((i)/Nk)*+j];//與Rcon異或

  }

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

  SubWord(temp);

  w[i*+] = (char)(w[(iNk)*+]^temp[]);

  w[i*+] = (char)(w[(iNk)*+]^temp[]);

  w[i*+] = (char)(w[(iNk)*+]^temp[]);

  w[i*+] = (char)(w[(iNk)*+]^temp[]);

  i++;

  }

  }

  /**

  * This method is used to do Sreplace

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

  * @param Nb the length of data block

  ///////////////////////////////////////////////////

  功能    S盒置換

  入口參數 Nb為以bit為單位的明文塊的大小

  state為明文塊

  ////////////////////////////////////////////////////

  */

  public    void  SubChar(char []stateint Nb)

  {

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

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

  }

  /**

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

  * @param Nb the length of data block

  /////////////////////////////////////////////////////

  功能    加密對明文塊進行移位運算

  入口參數state是明文塊

  Nb是以比特為單位的明文塊的大小

  //////////////////////////////////////////////////////

  */

  public     void  ShiftRows(char []state int Nb)

  {

  char[]  t = new char [];

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

  {

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

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

  state[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是以比特為單位的明文塊的大小

  //////////////////////////////////////////////////

  */

  public     void  MixColumns(char[]state int Nb)

  {

  int [] t = new int[];

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

  {

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

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

  {

  state[Nb*r+c] = (char)(Ffmul(xt[r])^Ffmul(xt[(r+)%])

  ^t[(r+)%]^t[(r+)%]);

  }

  }

  }

  /**

  * 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

  /////////////////////////////////////////////////////////

  功能返回兩個域元素AB的積;

  /////////////////////////////////////////////////////////

  */

  public     int Ffmul(int A int B)

  {

  //查對數表;

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

  A = Log[A];

  B = Log[B];

  A =(A+B)%xff;

  //查反對數表;

  A = Log_[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(bits)

  * @param round the index of current round

  ///////////////////////////////////////////////////////////////

  功能:   輪密鑰加變換;

  入口參數:   state明文塊

  w為子密鑰Nb為明文塊的大小round為當前加密的輪數;

  ///////////////////////////////////////////////////////////////

  */

  public     void  AddRoundKey(char[]state  int Nbint round)

  {

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

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

  state[r*Nb+c] = (char)(state[r*Nb+c]^w[round*+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(bits)

  * @param Nr the length of user key

  * @return the cryptograph

  */

  public     byte[]  Transform(char[]state int Nbint Nr)

  {

  int round=;

  AddRoundKey(stateNb);

  for(;round<Nr;round++)

  {

  SubChar(stateNb);

  ShiftRows(stateNb);

  MixColumns(stateNb);

  AddRoundKey(stateNbround*Nb);

  }

  SubChar(stateNb);

  ShiftRows(stateNb);

  AddRoundKey(stateNbround*Nb);

  return CharToByte(state);

  }

  /**

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

  * @param state is a array which contains the cryptograph to deencrypt

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

  * @param Nr the length of user key

  * @return the original text

  */

  public     byte[] ReTransform(char []state int Nbint Nr)

  {

  AddRoundKey(state NbNr*Nb);

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

  {

  InvShiftRows(stateNb);

  InvSubint(stateNb);

  AddRoundKey(stateNbround*Nb);

  InvMixColumns(stateNb);

  }

  InvShiftRows(stateNb);

  InvSubint(stateNb);

  AddRoundKey(stateNb);

  return CharToByte(state);

  }

  /**

  * This method is used to do Sreplace durying deencrypt cryptograph

  * @param state is a array which contains the cryptograph to deencrypt

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

  * @param Nr the length of user key

  /////////////////////////////////////////////////////////////

  功能解密時的S盒逆置換

  入口參數state為密文塊

  Nb為密文塊的大小

  */

  public    void  InvSubint(char []state int Nb)

  {

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

  state[i] = S_BOX_[state[i]%];

  }

  /**

  * This method is used to shift rows durying deencyrpt cryptograph

  * @param state is a array which contains the cryptograph to deencrypt

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

  ////////////////////////////////////////////////////////////////

  功能解密的時候的右移位變換

  入口參數state為密文塊

  Nb為密文塊的大小

  ////////////////////////////////////////////////////////////////

  */

  public    void  InvShiftRows(char[]state int Nb)

  {

  char [] t = new char[];

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

  {

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

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

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

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

  }

  }

  /**

  * This method is used to mix columns durying deencrypt cyyptograph

  * @param state is a array which contains the cryptograph to deencrypt

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

  //////////////////////////////////////////////////////////////

  功能解密時的列混合變換

  入口參數state為密文塊

  Nb為密文塊的大小

  //////////////////////////////////////////////////////////////

  */

  public    void  InvMixColumns(char []state int Nb)

  {

  char  []t = new char[];

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

  {

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

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

  {

  state[Nb*r+c] = (char)(Ffmul(xet[r])^Ffmul(xbt[(r+)%])

  ^Ffmul(xdt[(r+)%])^Ffmul(xt[(r+)%]));

  }

  }

  }

  /**

  * 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[datalength];

  for(int i = ;i<datalength;i++)

  A[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[datalength];

  for(int i = ;i<datalength;i++)

  A[i] = (byte)data[i];

  return A;

  }

  }

  package myLibAES;

  import javaioIOException;

  public class TestAes {

  /**

  * @param args

  */

  public static void main(String[] args) {

  // TODO Autogenerated method stub

  AES test = new AES();

  Systemoutprintln(testS_BOXlength);

  //(String OpenPathString SavePathString m_Keyint Nbint Nk)

  long time = SystemcurrentTimeMillis();

  try{

  testAES_Encrypt(G:\\mkvG:\\mkvtxt);

  testAES_DeEncrypt(G:\\mkvtxtG:\\DEmkv);

  }catch(IOException e){Systemoutprintln(e);}

  long time = SystemcurrentTimeMillis();

  time = timetime;

  Systemoutprintln(time);

  }

  }


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25654.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.