【问题标题】:Switching java stream to cipher stream将java流切换为密码流
【发布时间】:2015-12-08 09:25:42
【问题描述】:

我正在尝试创建一个协议,让客户端向服务器发送它的登录名。在此之后,服务器从服务器获取客户端密码并从中创建一个密码密钥。客户端根据输入的密码创建一个密钥。通过这种方式,我正在尝试建立安全连接。

但是,在发送用户名、获取密码等之后。我试图从 cypherstream 创建一个新的 objectinputstream 来读取数据,但它会阻塞。即使看了很多其他类似的问题,我也找不到让它工作的方法。

服务器端

private void switchToChipherStreams(String username) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException {
    byte key[] = dbMediator.getPasswordCypher(username);
    SecretKey key64 = new SecretKeySpec(key, "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, key64);
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
        Logger.getLogger(Connection.class.getName()).log(Level.SEVERE, null, ex);
    }
    out = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(), cipher));
    out.reset();
    out.flush();
    out.writeObject("switch");
    in = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipher));
}

客户端

private void switchToChipherStreams(String password) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException {
    //Generate key
    byte[] key = new byte[8];
    for (int i = 0; i < 8; i++) {
        if (password.length() > i) {
            key[i] = password.getBytes()[i];
        } else {
            key[i] = (byte) i;
        }
    }
    //Setup cipher streams
    SecretKey key64 = new SecretKeySpec(key, "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, key64);
    in = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipher));
    out = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(), cipher));
    out.reset();
    out.flush();
    out.writeObject("switch");
}

目前它正在抛出异常(无效标头),因为我正在尝试发送数据,但如果我不这样做,它只会阻塞。

谁能告诉我我在这里做错了什么,或者是否有可能更改为加密的对象输入流。

亲切的问候,

朱尔

编辑

更改密码以加密和解密输入和输出流,新代码:

服务器端

byte key[] = dbMediator.getPasswordCypher(username);
    SecretKey key64 = new SecretKeySpec(key, "Blowfish");
    Cipher cipheren = Cipher.getInstance("Blowfish");
    cipheren.init(Cipher.ENCRYPT_MODE, key64);
    Cipher cipherde = Cipher.getInstance("Blowfish");
    cipheren.init(Cipher.DECRYPT_MODE, key64);
    out = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(), cipheren));
    out.reset();
    out.flush();
    out.writeObject("switch");
    in = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipherde));

客户端

//Generate key
        byte[] key = new byte[8];
        for (int i = 0; i < 8; i++) {
            if (password.length() > i) {
                key[i] = password.getBytes()[i];
            } else {
                key[i] = (byte) i;
            }
        }
        //Setup cipher streams
        SecretKey key64 = new SecretKeySpec(key, "Blowfish");
        Cipher cipheren = Cipher.getInstance("Blowfish");
        cipheren.init(Cipher.ENCRYPT_MODE, key64);
        Cipher cipherde = Cipher.getInstance("Blowfish");
        cipheren.init(Cipher.DECRYPT_MODE, key64);
        out = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(), cipheren));
        out.reset();
        out.flush();
        out.writeObject("switch");
        in = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipherde));

现在解决了无效头部问题,但在调用 objectinputstream 构造函数时会冻结客户端和服务器。

【问题讨论】:

  • 你不需要在某个时候关闭流吗?
  • 关闭流导致关闭套接字
  • 在服务器端为每个客户端请求创建一个新线程怎么样?
  • 对于每个连接到服务器的客户端,我正在创建一个新线程。用户发送它的用户名,服务器从数据库获取密码并从密码创建一个密钥,客户端也是如此。如果客户端输入了错误的密码,则流将失败。但是,我必须进行切换。但是当我没有立即向它发送东西时,它会在创建新的 objectinputstream 时冻结。当我发送一些东西时,我得到一个无效的头部异常。

标签: java sockets encryption objectinputstream


【解决方案1】:

您不能从同一个 Cipher 对象创建密码输入输出流。您需要两个 Cipher 对象,一个处于 DECRYPT 模式,一个处于 ENCRYPT 模式。

在两端的ObjectInputStream 之前创建并刷新ObjectOutputStream

【讨论】:

  • 我更改了密码并在两边创建了objectoutputstream,然后创建了一个objectinputstream,但它仍然在调用objectinputstream的构造函数时冻结
  • 有些密码使用相同的算法进行加密和解密。
  • @zaph 当然有。我没有另外说明。 99.999% 的流密码属于该类别。重点是Cipherobjects,不能同时处于两种模式。
  • @JurClerkx 在创建ObjectInputStream 之前尝试刷新ObjectOutputStream。可能底层的CipherOutputStream 需要刷新。
猜你喜欢
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 2017-01-31
  • 2019-10-09
  • 1970-01-01
  • 1970-01-01
  • 2011-06-12
相关资源
最近更新 更多