Шифрование Android rc4

Я думаю, что что-то упускаю, я считаю, что изображение (преобразованное в байты) шифруется, но не расшифровывается, когда оно поступает на сторону клиента. Изображение вроде бы проходит проверку подписи 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;
}

person Melo    schedule 13.06.2017    source источник
comment
Я не думаю, что они существуют для RC4, пожалуйста, поправьте меня, если я ошибаюсь. RC4 — это потоковый шифр, не требующий заполнения.   -  person Melo    schedule 13.06.2017
comment
Я не понял, вы предлагаете удалить cipher.doFinal()? Будут ли данные по-прежнему зашифрованы?   -  person Melo    schedule 13.06.2017
comment
Хорошо, вы устранили мою путаницу, это работает, спасибо, приятель. Я не был уверен, могу ли я пропустить cipher.doFinal. Вы можете структурировать свой ответ, и я приму его.   -  person Melo    schedule 13.06.2017


Ответы (1)


CipherInputStream и CipherOutputStream предназначены для выполнения всей тяжелой работы, поэтому вы просто предоставляете их с помощью инициализированного экземпляра Cipher, а затем используйте потоковые методы записи и чтения. По большей части вы можете наслаивать их, как и без входных и выходных потоков, но есть одна тонкость: когда используется блочный шифр, нет хорошего способа сигнализировать CipherOutputStream, что ему нужно вызвать Cipher.doFinal(). Единственный поддерживаемый способ — вызвать close() метод. Эти вызовы close() распространяются на другие обернутые потоки, и в этом случае, когда выходной поток сокета обернут, это заканчивается закрытием сокета в качестве побочного эффекта. Это может быть вполне приемлемым поведением, но вы должны знать об этом. В этом случае, поскольку вы используете байт-ориентированный потоковый шифр (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;
    }
}
person President James K. Polk    schedule 13.06.2017