2013-08-16 141 views
1

我正在尝试制作一个使用AES加密发送数据的聊天程序(基于this),但我遇到了一些问题。我已经对消息进行了加密(我认为... [这只是我的第二个程序,所以我对Java真的很陌生]),但是当我尝试解密消息时,程序无法找到之前创建的符号“cipher” 。继承人错误所在:找不到符号/变量错误

public void run() throws IOException { 

// Make connection and initialize streams 
String serverAddress = getServerAddress(); 
Socket socket = new Socket(serverAddress, 9001); 
in = new BufferedReader(new InputStreamReader(
    socket.getInputStream())); 
out = new PrintWriter(socket.getOutputStream(), true); 
// Process all messages from server, according to the protocol. 
while (true) { 
    String line = in.readLine(); 
if (line.startsWith("SUBMITNAME")) { 
     out.println(getName()); 
    } else if (line.startsWith("NAMEACCEPTED")) { 
     textField.setEditable(true); 
    } else if (line.startsWith("MESSAGE")) { 
       //DECRYPTION 
       messageArea.append(line.substring(8) + "\n"); 
       cipher.init(Cipher.DECRYPT_MODE, key); 
       line = new String(cipher.doFinal(line)); 
       System.out.println(line); 
    } 
} 
} 

其中cipher创建继承人:

public void actionPerformed(ActionEvent e) { 
    try { 
     String input = (textField.getText()); 
     //ENCRYPTION 
     MessageDigest md5 = MessageDigest.getInstance("MD5"); 
     md5.update("So What's Up Doc?".getBytes()); 

     SecretKeySpec key = new SecretKeySpec(md5.digest(), "AES"); 

     Cipher cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, key); 

     byte encryptedMessage[] = cipher.doFinal(input.getBytes()); 
     //Sends the encrypted version of message 
     System.out.println(encryptedMessage); 
     out.println(encryptedMessage); 
     //Clears the input box 
     textField.setText(""); 
    } catch ( NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex) { 
     Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    } 

完整的代码是在这里:

package Chat.Application; 

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.Socket; 

import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.JTextField; 

import java.security.GeneralSecurityException; 
import java.security.InvalidKeyException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.SecretKeySpec; 
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; 
/** 
* A simple Swing-based client for the chat server. Graphically 
* it is a frame with a text field for entering messages and a 
* textarea to see the whole dialog. 
* 
* The client follows the Chat Protocol which is as follows. 
* When the server sends "SUBMITNAME" the client replies with the 
* desired screen name. The server will keep sending "SUBMITNAME" 
* requests as long as the client submits screen names that are 
* already in use. When the server sends a line beginning 
* with "NAMEACCEPTED" the client is now allowed to start 
* sending the server arbitrary strings to be broadcast to all 
* chatters connected to the server. When the server sends a 
* line beginning with "MESSAGE " then all characters following 
* this string should be displayed in its message area. 
*/ 
public class ChatClient { 

    BufferedReader in; 
    PrintWriter out; 
    JFrame frame = new JFrame("ELECTRON Chatroom"); 
    JTextField textField = new JTextField(40); 
    JTextArea messageArea = new JTextArea(8, 40); 

    /** 
    * Constructs the client by laying out the GUI and registering a 
    * listener with the textfield so that pressing Return in the 
    * listener sends the textfield contents to the server. Note 
    * however that the textfield is initially NOT editable, and 
    * only becomes editable AFTER the client receives the NAMEACCEPTED 
    * message from the server. 
    */ 
    public ChatClient() { 

     // Layout GUI 
     textField.setEditable(false); 
     messageArea.setEditable(false); 
     messageArea.setWrapStyleWord(true); 
     messageArea.setLineWrap(true); 
     frame.getContentPane().add(textField, "North"); 
     frame.getContentPane().add(new JScrollPane(messageArea), "Center"); 
     frame.pack(); 
     // Add Listeners 
     textField.addActionListener(new ActionListener() { 
      /** 
      * Responds to pressing the enter key in the textfield by sending 
      * the contents of the text field to the server. Then clear 
      * the text area in preparation for the next message. 
      */ 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      try { 
       String input = (textField.getText()); 
       //ENCRYPTION 
       MessageDigest md5 = MessageDigest.getInstance("MD5"); 
       md5.update("So What's Up Doc?".getBytes()); 

       SecretKeySpec key = new SecretKeySpec(md5.digest(), "AES"); 

       Cipher cipher = Cipher.getInstance("AES"); 
       cipher.init(Cipher.ENCRYPT_MODE, key); 

       byte encryptedMessage[] = cipher.doFinal(input.getBytes()); 
       //Sends the encrypted version of message 
       System.out.println(encryptedMessage); 
       out.println(encryptedMessage); 
       //Clears the input box 
       textField.setText(""); 
      } catch ( NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex) { 
       Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex); 
      } 
      } 
     }); 
    } 

    /** 
    * Prompt for and return the address of the server. 
    */ 
    private String getServerAddress() { 
     return JOptionPane.showInputDialog(
      frame, 
      "Enter IP Address of the Server:", 
      "ELECTRON Chatroom", 
      JOptionPane.QUESTION_MESSAGE); 
    } 

    /** 
    * Prompt for and return the desired screen name. 
    */ 
    private String getName() { 
     return JOptionPane.showInputDialog(
      frame, 
      "Choose a screen name:", 
      "Screen name selection", 
      JOptionPane.PLAIN_MESSAGE); 
    } 

    /** 
    * Connects to the server then enters the processing loop. 
    */ 
    public void run() throws IOException { 

     // Make connection and initialize streams 
     String serverAddress = getServerAddress(); 
     Socket socket = new Socket(serverAddress, 9001); 
     in = new BufferedReader(new InputStreamReader(
      socket.getInputStream())); 
     out = new PrintWriter(socket.getOutputStream(), true); 
     // Process all messages from server, according to the protocol. 
     while (true) { 
      String line = in.readLine(); 
     if (line.startsWith("SUBMITNAME")) { 
       out.println(getName()); 
      } else if (line.startsWith("NAMEACCEPTED")) { 
       textField.setEditable(true); 
      } else if (line.startsWith("MESSAGE")) { 
         //DECRYPTION 
         messageArea.append(line.substring(8) + "\n"); 
         cipher.init(Cipher.DECRYPT_MODE, key); 
         line = new String(cipher.doFinal(line)); 
         System.out.println(line); 
      } 
     } 
    } 

    /** 
    * Runs the client as an application with a closeable frame. 
    */ 
    public static void main(String[] args) throws Exception { 
     ChatClient client = new ChatClient(); 
     client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     client.frame.setVisible(true); 
     client.run(); 
    } 
} 

AES加密的代码是从here

我相信这是一个简单的解决方案,怀疑AES加密部分与我有什么关系但不妨添加它。感谢你的帮助! - 银

编辑 - 错误:

no suitable method found for doFinal(String) 
    method Cipher.doFinal(ByteBuffer,ByteBuffer) is not applicable 
     (actual and formal argument lists differ in length) 
    method Cipher.doFinal(byte[],int,int,byte[],int) is not applicable 
     (actual and formal argument lists differ in length) 
    method Cipher.doFinal(byte[],int,int,byte[]) is not applicable 
     (actual and formal argument lists differ in length) 
    method Cipher.doFinal(byte[],int,int) is not applicable 
     (actual and formal argument lists differ in length) 
    method Cipher.doFinal(byte[]) is not applicable 
     (actual argument String cannot be converted to byte[] by method invocation conversion) 
    method Cipher.doFinal(byte[],int) is not applicable 
     (actual and formal argument lists differ in length) 
    method Cipher.doFinal() is not applicable 
     (actual and formal argument lists differ in length) 

回答

1

cicher一个全局变量。声明它在你的类的顶层:

Cipher cipher; 

变化:

Cipher cipher = Cipher.getInstance("AES"); 

到:

cipher = Cipher.getInstance("AES"); 

添加一张支票null这里:

if (cipher != null) { 
    cipher.init(Cipher.DECRYPT_MODE, key); 
    line = new String(cipher.doFinal(line)); 
    System.out.println(line); 
} 

基本上,变量cipher不知道你在哪里试图使用它。在顶层声明它会使整个课程都可见。如果actionPerformed(ActionEvent)run()在此<订单中调用,则不需要检查null

+0

除了包含“line = new String(cipher.doFinal(line));”的行外,那里有一个很大的错误。我在我的问题中列出了错误 – Silver

+0

关于如何解决它的任何想法?也感谢所有的帮助! – Silver

+0

@Silver你会发现错误是:'Cipher.doFinal()'是一个重载方法,没有一个方法签名匹配 - 'Cipher.doFinal(String)'这就是你正在做的事情。看看密码API,并确认'Cipher.doFinal(String)'不存在。我建议你现在就离开'AES'。 – Vikram