Androidrc4加密

Android rc4 encryption

我想我遗漏了一些东西,我相信图像(转换为字节)在到达客户端时正在加密但没有解密。图像似乎通过了RSA签名验证,但不知何故无法查看。

客户端代码:

    public void aliceEncrypt(byte[] plaintext, byte[] sharedSecret) {

    Cipher cipher;
    byte[] encrypted = null;
    try {
        cipher = Cipher.getInstance("RC4");
        Key sk = new SecretKeySpec(sharedSecret, "RC4");
        cipher.init(Cipher.ENCRYPT_MODE, sk);
        encrypted = cipher.doFinal(plaintext);
        CipherOutputStream cos = new CipherOutputStream(socket.getOutputStream(), cipher);
        ObjectOutputStream oos = new ObjectOutputStream(cos);
        oos.writeObject(encrypted);
        oos.flush();

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

服务器端代码:

public byte[] bobDecrypt( byte[] sharedSecret) {


    Cipher cipher = null;
    byte[] bytes = null;
    byte[] decrypted = null;
    try {
        cipher = Cipher.getInstance("RC4");
        Key sk = new SecretKeySpec(sharedSecret, "RC4");
        cipher.init(Cipher.DECRYPT_MODE, sk);
        CipherInputStream cis = new CipherInputStream(socket.getInputStream(), cipher);
        ObjectInputStream ois = new ObjectInputStream(cis);
        bytes =  (byte[])ois.readObject();
        decrypted = cipher.doFinal(bytes);

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

CipherInputStream and CipherOutputStream are meant to do all the heavy lifting, so you just supply them with an initialized Cipher instance and then use the write and read stream methods. For the most part you can layer these as with out input and output streams, but there is one subtlety: when a block cipher is used, there is no good way to signal the CipherOutputStream that it needs to call Cipher.doFinal(). The only supported way is to call the close() 方法。这些 close() 调用传播 到其他包装流,在这种情况下,套接字 Outputstream 被包装,它最终会关闭套接字作为副作用。这可能是完全可以接受的行为,但您需要意识到这一点。在这种情况下,因为您使用的是面向字节的流密码 (RC4),所以没有填充,所以 Cipher.doFinal() 基本上是一个空操作(好吧,它确实重置了密码状态),所以调用 flush() 与调用 close() 一样好。下面的代码基本上是您修改​​的代码,以正确显示如何分层和使用各种流。

public void aliceEncrypt(byte[] plaintext, byte[] sharedSecret, Socket socket) {

    try {
        Cipher cipher = Cipher.getInstance("RC4/ECB/NoPadding");
        Key sk = new SecretKeySpec(sharedSecret, "RC4");
        cipher.init(Cipher.ENCRYPT_MODE, sk);
        CipherOutputStream cos = new CipherOutputStream(socket.getOutputStream(), cipher);
        ObjectOutputStream oos = new ObjectOutputStream(cos);
        oos.writeObject(plaintext);
        oos.close();

    } catch (Exception e) {
        e.printStackTrace();
    }
}


public byte[] bobDecrypt( byte[] sharedSecret, Socket socket) {


    try {
        Cipher cipher = Cipher.getInstance("RC4/ECB/NoPadding");
        Key sk = new SecretKeySpec(sharedSecret, "RC4");
        cipher.init(Cipher.DECRYPT_MODE, sk);
        CipherInputStream cis = new CipherInputStream(socket.getInputStream(), cipher);
        ObjectInputStream ois = new ObjectInputStream(cis);
        byte[] bytes = (byte[]) ois.readObject();
        return bytes;

    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}