【问题标题】:Socket and ObjectInputStream in Java - AndroidJava 中的 Socket 和 ObjectInputStream - Android
【发布时间】:2014-08-24 06:53:01
【问题描述】:

我在使用 Java 的 Cipher 类时遇到了 Socket 和 ObjectInputStream 的问题。 我使用一个客户端 Android,它在 Socket 上编写一个 ObjectOutputStream,以及一个从同一个 Socket 读取这个 ObjectInputStream 的客户端 Java。 这是代码客户端/服务器

客户

[代码]

 public static void functionRegistration(String usr, String pwd) throws UnknownHostException, IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException{

    Socket socket = new Socket(SERVER_ADDRESS_STRING, PORT_NO);
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    socket.setSoTimeout(DEFAULT_TIMEOUT);

    if(!socket.isConnected()){
        System.out.println("[!] [Client] Connection problem!");
        socket.close();
        return;
    }

    //Diffie-Hellman
    BigInteger shared_key = DiffieHellmanExchangeClient(socket, br, bw);
    byte[] hash = ObjectHash.getByteHashCode(shared_key, SECURE_HASH_TYPE.SHA384);

    //Extract IV and cipherKey
    byte[] IV = new byte[16];
    byte[] cipherKey = new byte[32];

    int i, limit;

    for(i = 0; i < IV.length; i++)
        IV[i] = hash[i];

    limit = i;

    for(; i < hash.length; i++)
        cipherKey[i - limit] = hash[i];

    //Send username
    bw.write(usr);
    bw.write("\r\n");
    bw.flush();


    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

    //Hash password
    String passwordHash = new String(ObjectHash.getByteHashCode(pwd, SECURE_HASH_TYPE.SHA512));

    //Cipher password
    String encryptedPasswordHash = new String(cipherMessage(passwordHash, cipherKey));

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    IvParameterSpec ivparameters = new IvParameterSpec(IV);
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), ivparameters);


    oos.writeObject(new SealedObject(encryptedPasswordHash, cipher));
    oos.flush();


    if(br.readLine().compareTo("ACK") == 0)
        Log.d("ACK", "ACK_RECEIVED");

    else
        Log.d("ACK","Something was wrong");

    br.close();
    bw.close();
    socket.close();
}

[\代码]

服务器

[代码]

  private void getRegistrationUser() throws IOException, InvalidKeyException, InvalidAlgorithmParameterException{
    String username = br.readLine();

    System.out.println("[+] [Server - Thread " + Thread.currentThread().getId() + "] Username received");

    //SHA384 of shared key
    byte[] hash = ObjectHash.getByteHashCode(shared_key, SECURE_HASH_TYPE.SHA384);

    byte[] IV = new byte[16];
    byte[] cipherKey = new byte[32];

    int j, limit;

    for(j = 0; j < IV.length; j++)
        IV[j] = hash[j];

    limit = j;

    for(; j < hash.length; j++)
        cipherKey[j - limit] = hash[j];

    try{

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivparameters = new IvParameterSpec(IV);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), ivparameters);

        ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
        String encryptedHashPassword = (String)((SealedObject)ois.readObject()).getObject(cipher);

        String decryptedHashPassword = decipherMessage(encryptedHashPassword, cipherKey);

        ois.close();

        sendACK();

    }
    catch (IOException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    }   
}

[\代码]

代码 cipherMessage 和 decipherMessage 中的两个函数使用 Twofish Cipher 分别使用密钥对数据进行加密和解密

问题是:我在调试阶段注意到服务器阻塞了 newObjectInputStream 并且不可能读取客户端写入的对象

我该如何解决我的问题?

【问题讨论】:

  • 你的代码在没有加密/解密的情况下能正常工作吗?
  • 如果我删除了 Twofish 的操作,客户端的 cipherMessage 和服务器的 decipherMessage,代码不起作用。在调试中,我看到当打开 ObjectInputStream 时服务器被阻止。我不知道为什么。我还在客户端刷新了 ObjectOutputStream
  • 服务器代码中的 Diffie-Hellman 在哪里?你是如何调试你的应用程序的?
  • Diffie-Hellman 是正确的。我测试了它。问题是我无法在android和服务器java之间的socket上传输加密信息,但是在客户端java和服务器java之间没有twofish
  • 这可能是由于当时的流处理;尝试在缓冲阅读器上使用ObjectInputStream;它可能会做它应该做的事情并从输入流中读取信息并将其缓冲,将其从ObjectInputStream 试图读取的流中删除。

标签: java android security encryption objectinputstream


【解决方案1】:

您不能在同一个套接字上使用多个缓冲流。他们会互相窃取数据。对所有事物都使用对象流。

【讨论】:

  • 所以对你来说,问题不在于使用 Twofish 密码加密和解密信息。但我还有另一个问题:为什么如果我将这段代码复制并粘贴到客户端和服务器 java 上,它可以正常工作,完全与 bufferedreader 和 objectinputstream 一起使用???
  • 我猜你会走运的。未指定它提前读取多少。
  • 哈哈。然后我尝试消除缓冲读取器并且我只使用 objectinputstream,在接下来的一个小时内我会告诉你我是否至少解决了这个问题
  • @owlstead 不仅没有指定,而且还不确定。它不仅取决于未指定的缓冲区大小,还取决于读取时套接字接收缓冲区中已经存在的数据量。
  • 此解决方案无法工作,因为我有另一个使用 BufferedReader 和 BufferedWriter 的函数 (DiffieHellmanExchange)。如果我分别用 ObjectInputStream 和 ObjectOutputStream 修改这个函数不起作用。
猜你喜欢
  • 1970-01-01
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
相关资源
最近更新 更多