對於任意長度的明文,AES首先對其進行分組,每組的長度爲128位。分組以後將分別對每一個128位的明文分組進行加密。java
(1)將128位AES明文分組放入狀態矩陣中。node
(2)AddRoundKey變換:對狀態矩陣進行AddRoundKey變換,與膨脹後的密鑰進行異或操做(密鑰膨脹將在實驗原理七中詳細討論)。算法
(3)10輪循環:AES對狀態矩陣進行了10輪相似的子加密過程。前9輪子加密過程當中,每一輪子加密過程包括4種不一樣的變換,而最後一輪只有3種變換,前9輪的子加密步驟以下:windows
(4)通過10輪循環的狀態矩陣中的內容就是加密後的密文。數組
類 Cipher
java.lang.Object
javax.crypto.Cipher,主要提供加密解密功能服務器
類 KeyGenerator
java.lang.Object
javax.crypto.KeyGenerator,此類提供(對稱)密鑰生成器的功能。網絡
接口 SecretKey
全部超級接口:
Key, Serializable
全部已知子接口:
PBEKey
全部已知實現類:
KerberosKey, SecretKeySpec多線程
AesJM.javaapp
package AesMmx; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class AesJM { public static String MmxEncode(String theKey, String theText) { try { KeyGenerator k = KeyGenerator.getInstance("AES");//密鑰生成器 k.init(128, new SecureRandom(theKey.getBytes()));//初始化128位生成器 SecretKey ori_key = k.generateKey();//產生密鑰 byte[] sz = ori_key.getEncoded();//密鑰轉爲二進制數組 SecretKey key = new SecretKeySpec(sz, "AES");//轉爲AES密鑰 Cipher c = Cipher.getInstance("AES");//定義AES密碼器 c.init(Cipher.ENCRYPT_MODE, key);//傳入密碼初始化密碼器 byte[] content_b = theText.getBytes("utf-8");//獲取文本的utf-8二進制數組 byte[] miwen_b = c.doFinal(content_b);//加密 String miwen = new String(new BASE64Encoder().encode(miwen_b));//加密後的二進制轉爲String return miwen; } catch (Exception e) { e.printStackTrace(); } return null; } public static String MmxDncode(String theKey, String theText) throws UnsupportedEncodingException, IOException { try { KeyGenerator k = KeyGenerator.getInstance("AES"); k.init(128, new SecureRandom(theKey.getBytes())); SecretKey ori_key = k.generateKey(); byte[] sz = ori_key.getEncoded(); SecretKey key = new SecretKeySpec(sz, "AES"); Cipher c = Cipher.getInstance("AES"); c.init(Cipher.DECRYPT_MODE, key); byte[] content_b = new BASE64Decoder().decodeBuffer(theText); byte[] mingwen_b = c.doFinal(content_b);//解密 String mingwen = new String(mingwen_b, "utf-8"); return mingwen; } catch (Exception e) { e.printStackTrace(); } return null; } }
Net.javadom
package AesMmx; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; public class Net { //網絡功能,實現互相傳數據功能 private static int po = 6666; //默認端口號 public static void setPo(int port) { //設置端口號 po = port; } public static void ListenNet() throws IOException { //監聽端口功能,接受數據 while (true) { ServerSocket serverSocket = new ServerSocket(po); //建立服務器socket Socket socket = serverSocket.accept(); //監聽端口 InputStream is = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); //輸入流 String info = null; Date time = new Date(); String theTime = "" + time.getTime(); //獲取時間戳 File file = new File(theTime + ".txt"); System.out.println(theTime + ".txt"); //收到的信息保存到文件 BufferedWriter bufw = new BufferedWriter(new FileWriter(file)); while ((info = br.readLine()) != null) { bufw.write(info); System.out.println("客戶端消息" + info); } socket.shutdownInput(); bufw.close(); br.close(); isr.close(); is.close(); socket.close(); serverSocket.close(); } } public static void send(String ip, int ipport, String str) throws IOException { Socket socket = new Socket(ip, ipport); //建立socket OutputStream os = socket.getOutputStream(); PrintWriter pw = new PrintWriter(os); //輸出流 pw.write(str); //將數據寫出 pw.flush(); socket.shutdownOutput(); pw.close(); os.close(); socket.close(); } public void run(int port) { while (true) { try { ListenNet(); //一直監聽 } catch (IOException ex) { Logger.getLogger(Net.class.getName()).log(Level.SEVERE, null, ex); } } } }
GUI主要組件:
jPanel1 = new javax.swing.JPanel(); jPanel2 = new javax.swing.JPanel(); jLabel2 = new javax.swing.JLabel(); dstIP = new javax.swing.JTextField(); //目的IP框 dstPort = new javax.swing.JTextField(); //目的IP端口框 send = new javax.swing.JButton(); //發送按鈕 jLabel3 = new javax.swing.JLabel(); lisPort = new javax.swing.JTextField(); //監聽端口框 listen = new javax.swing.JButton(); //監聽按鈕 jPanel3 = new javax.swing.JPanel(); miyue = new javax.swing.JPasswordField(); //密碼框 jLabel1 = new javax.swing.JLabel(); jSeparator1 = new javax.swing.JSeparator(); jScrollPane1 = new javax.swing.JScrollPane(); content = new javax.swing.JTextArea(); //文本框 jSeparator2 = new javax.swing.JSeparator(); jPanel4 = new javax.swing.JPanel(); jButton1 = new javax.swing.JButton(); jButton2 = new javax.swing.JButton(); menulist = new javax.swing.JMenuBar(); //菜單欄 jMenu3 = new javax.swing.JMenu(); //文件按鈕 open = new javax.swing.JMenuItem(); //打開文件 save = new javax.swing.JMenuItem(); //保存文件 keyMenu = new javax.swing.JMenu(); //密碼按鈕 openKey = new javax.swing.JMenuItem(); //打開密碼 saveKey = new javax.swing.JMenuItem(); //保存密碼
MmxGui.java
package AesMmx; import java.awt.FileDialog; import java.awt.Frame; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; public class MmxGui extends javax.swing.JFrame { //圖形界面 private Frame f; //窗體 private File file; //windows文件 public MmxGui() { initComponents(); //初始化 } private void initComponents() { jPanel1 = new javax.swing.JPanel(); jPanel2 = new javax.swing.JPanel(); jLabel2 = new javax.swing.JLabel(); dstIP = new javax.swing.JTextField(); //目的IP框 dstPort = new javax.swing.JTextField(); //目的IP端口框 send = new javax.swing.JButton(); //發送按鈕 jLabel3 = new javax.swing.JLabel(); lisPort = new javax.swing.JTextField(); //監聽端口框 listen = new javax.swing.JButton(); //監聽按鈕 jPanel3 = new javax.swing.JPanel(); miyue = new javax.swing.JPasswordField(); //密碼框 jLabel1 = new javax.swing.JLabel(); jSeparator1 = new javax.swing.JSeparator(); jScrollPane1 = new javax.swing.JScrollPane(); content = new javax.swing.JTextArea(); //文本框 jSeparator2 = new javax.swing.JSeparator(); jPanel4 = new javax.swing.JPanel(); jButton1 = new javax.swing.JButton(); jButton2 = new javax.swing.JButton(); menulist = new javax.swing.JMenuBar(); //菜單欄 jMenu3 = new javax.swing.JMenu(); //文件按鈕 open = new javax.swing.JMenuItem(); //打開文件 save = new javax.swing.JMenuItem(); //保存文件 keyMenu = new javax.swing.JMenu(); //密碼按鈕 openKey = new javax.swing.JMenuItem(); //打開密碼 saveKey = new javax.swing.JMenuItem(); //保存密碼 setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("AES加密解密-CJB"); jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder()); jLabel2.setFont(new java.awt.Font("等線 Light", 0, 24)); jLabel2.setText("目的IP"); jPanel2.add(jLabel2); dstIP.setFont(new java.awt.Font("等線 Light", 0, 24)); dstIP.setText("127.0.0.1"); dstIP.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { dstIPActionPerformed(evt); } }); jPanel2.add(dstIP); dstPort.setFont(new java.awt.Font("等線 Light", 0, 24)); dstPort.setText("6666"); jPanel2.add(dstPort); send.setFont(new java.awt.Font("等線 Light", 0, 24)); send.setText("發送"); send.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { sendActionPerformed(evt); } }); jPanel2.add(send); jLabel3.setFont(new java.awt.Font("等線 Light", 0, 24)); jLabel3.setText("監聽端口"); jPanel2.add(jLabel3); lisPort.setFont(new java.awt.Font("等線 Light", 0, 24)); lisPort.setText("6666"); jPanel2.add(lisPort); listen.setFont(new java.awt.Font("等線 Light", 0, 24)); listen.setText("開啓監聽"); listen.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { listenActionPerformed(evt); } }); jPanel2.add(listen); jPanel3.setBorder(javax.swing.BorderFactory.createEtchedBorder()); miyue.setFont(new java.awt.Font("等線 Light", 0, 24)); miyue.addKeyListener(new java.awt.event.KeyAdapter() { public void keyPressed(java.awt.event.KeyEvent evt) { miyueKeyPressed(evt); } }); jLabel1.setFont(new java.awt.Font("等線 Light", 0, 24)); jLabel1.setText("密碼"); content.setColumns(20); content.setRows(5); jScrollPane1.setViewportView(content); jPanel4.setBorder(javax.swing.BorderFactory.createEtchedBorder()); jButton1.setFont(new java.awt.Font("等線 Light", 0, 24)); jButton1.setText("加密"); jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton1ActionPerformed(evt); } }); jPanel4.add(jButton1); jButton2.setFont(new java.awt.Font("等線 Light", 0, 24)); jButton2.setText("解密"); jButton2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton2ActionPerformed(evt); } }); jPanel4.add(jButton2); javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup() .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jSeparator1) .addGroup(jPanel3Layout.createSequentialGroup() .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 115, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(miyue)))) .addGroup(jPanel3Layout.createSequentialGroup() .addGap(128, 128, 128) .addComponent(jScrollPane1)) .addGroup(jPanel3Layout.createSequentialGroup() .addContainerGap() .addComponent(jSeparator2)) .addGroup(jPanel3Layout.createSequentialGroup() .addContainerGap() .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addContainerGap()) ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(miyue, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(14, Short.MAX_VALUE)) ); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 637, Short.MAX_VALUE)) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER); jMenu3.setText("文件"); open.setText("打開"); open.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { openActionPerformed(evt); } }); jMenu3.add(open); save.setText("保存"); save.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { saveActionPerformed(evt); } }); jMenu3.add(save); menulist.add(jMenu3); keyMenu.setText("密碼"); openKey.setText("導入"); openKey.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { openKeyActionPerformed(evt); } }); keyMenu.add(openKey); saveKey.setText("導出"); saveKey.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { saveKeyActionPerformed(evt); } }); keyMenu.add(saveKey); menulist.add(keyMenu); setJMenuBar(menulist); pack(); } private void dstIPActionPerformed(java.awt.event.ActionEvent evt) { } private void openActionPerformed(java.awt.event.ActionEvent evt) { f = new Frame("文件瀏覽"); f.setBounds(300, 100, 650, 600); openDia = new FileDialog(f, "打開", FileDialog.LOAD); openDia.setVisible(true); String dirpath = openDia.getDirectory(); String fileName = openDia.getFile(); if (dirpath == null || fileName == null) { return; } else { content.setText(null); } File file = new File(dirpath, fileName); try { BufferedReader bufr = new BufferedReader(new FileReader(file)); String line = null; while ((line = bufr.readLine()) != null) { content.append(line + "\r\n"); } bufr.close(); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } } private void sendActionPerformed(java.awt.event.ActionEvent evt) { try { Net.send(dstIP.getText(), Integer.parseInt(dstPort.getText()), content.getText()); } catch (IOException ex) { Logger.getLogger(MmxGui.class.getName()).log(Level.SEVERE, null, ex); } } private void listenActionPerformed(java.awt.event.ActionEvent evt) { Net.setPo(Integer.parseInt(lisPort.getText())); Runnable r = () -> { try { Net.ListenNet(); } catch (IOException ex) { Logger.getLogger(MmxGui.class.getName()).log(Level.SEVERE, null, ex); } }; new Thread(r).start(); } @SuppressWarnings("deprecation") private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { content.setText(AesJM.MmxEncode(miyue.getText(), content.getText())); } @SuppressWarnings("deprecation") private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { try { content.setText(AesJM.MmxDncode(miyue.getText(), content.getText())); } catch (IOException ex) { Logger.getLogger(MmxGui.class.getName()).log(Level.SEVERE, null, ex); } } private void saveActionPerformed(java.awt.event.ActionEvent evt) { saveDia = new FileDialog(f, "保存", FileDialog.SAVE); if (file == null) { saveDia.setVisible(true); String dirpath = saveDia.getDirectory(); String fileName = saveDia.getFile(); if (dirpath == null || fileName == null) { return; } else { file = new File(dirpath, fileName); } } try { BufferedWriter bufw = new BufferedWriter(new FileWriter(file)); String text = content.getText(); bufw.write(text); bufw.close(); } catch (IOException e1) { e1.printStackTrace(); } } private void miyueKeyPressed(java.awt.event.KeyEvent evt) { } private void openKeyActionPerformed(java.awt.event.ActionEvent evt) { f = new Frame("密碼瀏覽"); f.setBounds(300, 100, 650, 600); openDia = new FileDialog(f, "打開", FileDialog.LOAD); openDia.setVisible(true); String dirpath = openDia.getDirectory(); String fileName = openDia.getFile(); if (dirpath == null || fileName == null) { return; } else { miyue.setText(null); } File file = new File(dirpath, fileName); try { BufferedReader bufr = new BufferedReader(new FileReader(file)); String line = null; while ((line = bufr.readLine()) != null) { miyue.setText(line); } bufr.close(); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } } @SuppressWarnings("deprecation") private void saveKeyActionPerformed(java.awt.event.ActionEvent evt) { saveDia = new FileDialog(f, "保存", FileDialog.SAVE); if (file == null) { saveDia.setVisible(true); String dirpath = saveDia.getDirectory(); String fileName = saveDia.getFile(); if (dirpath == null || fileName == null) { return; } else { file = new File(dirpath, fileName); } } try { BufferedWriter bufw = new BufferedWriter(new FileWriter(file)); String text = miyue.getText(); bufw.write(text); bufw.close(); } catch (IOException e1) { e1.printStackTrace(); } } public static void main(String args[]) { try { for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { javax.swing.UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (ClassNotFoundException ex) { java.util.logging.Logger.getLogger(MmxGui.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (InstantiationException ex) { java.util.logging.Logger.getLogger(MmxGui.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { java.util.logging.Logger.getLogger(MmxGui.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (javax.swing.UnsupportedLookAndFeelException ex) { java.util.logging.Logger.getLogger(MmxGui.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new MmxGui().setVisible(true); } }); } private FileDialog openDia, saveDia; //windows文件 private javax.swing.JTextArea content; private javax.swing.JTextField dstIP; private javax.swing.JTextField dstPort; private javax.swing.JButton jButton1; private javax.swing.JButton jButton2; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JMenu jMenu3; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanel4; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JSeparator jSeparator1; private javax.swing.JSeparator jSeparator2; private javax.swing.JMenu keyMenu; private javax.swing.JTextField lisPort; private javax.swing.JButton listen; private javax.swing.JMenuBar menulist; private javax.swing.JPasswordField miyue; private javax.swing.JMenuItem open; private javax.swing.JMenuItem openKey; private javax.swing.JMenuItem save; private javax.swing.JMenuItem saveKey; private javax.swing.JButton send; }
此次實驗須要完成:圖形界面、打開保存文件、網絡傳輸、AES加密解密。其中,最難的部分是AES加密解密算法的實現,須要咱們參考Java文檔,查詢相關加密、解密內容,同時須要咱們合理的應用內置類實現加密解密功能。打開、保存文件是另一個難點。我查閱相關資料,主要是用以下圖實現:
保存和打開文件的過程我是使用字符打開,未實現用二進制保存和打開,且部分格式保存會使其成爲無效文件。網絡功能主要是應用服務器socket和客戶端socket實現。用多線程開啓服務器監聽,當須要發送信息時建立客戶端socket進行通訊。GUI部分,由於是用netbeans工具,隱藏隱祕信息的文本框利用以下對象實現:
通過此次實驗,我對密碼學中的加密、解密原理有更深的認識和研究,也體會到密碼學與現實生活的結合、應用。