对于任意长度的明文,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工具,隐藏隐秘信息的文本框利用以下对象实现:
通过此次实验,我对密码学中的加密、解密原理有更深的认识和研究,也体会到密码学与现实生活的结合、应用。