Проблема с шифрованием и дешифрованием файла через AES на Android - PullRequest
0 голосов
/ 02 июля 2019

Я пытаюсь зашифровать голосовые файлы, которые отправляю на свой сервер. Я использую следующий процесс:

запись голоса в файл> преобразование файла в байтовый массив> шифрование байтового массива сгенерированным ключом> сохранение ключа в строку> загрузка байтового массива> загрузка файла с сервера> преобразование его в байтовый массив> дешифрование сгенерированным ключом <- здесь Я получаю ошибку </p>

javax.crypto.AEADBadTagException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
2019-07-02 17:20:51.771 25417-25448/cz.magician.justtalk W/System.err:     at java.lang.reflect.Constructor.newInstance0(Native Method)
2019-07-02 17:20:51.771 25417-25448/cz.magician.justtalk W/System.err:     at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
2019-07-02 17:20:51.771 25417-25448/cz.magician.justtalk W/System.err:     at com.android.org.conscrypt.OpenSSLCipher$EVP_AEAD.throwAEADBadTagExceptionIfAvailable(OpenSSLCipher.java:1200)
2019-07-02 17:20:51.771 25417-25448/cz.magician.justtalk W/System.err:     at com.android.org.conscrypt.OpenSSLCipher$EVP_AEAD.doFinalInternal(OpenSSLCipher.java:1229)
2019-07-02 17:20:51.771 25417-25448/cz.magician.justtalk W/System.err:     at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:363)
2019-07-02 17:20:51.771 25417-25448/cz.magician.justtalk W/System.err:     at javax.crypto.Cipher.doFinal(Cipher.java:2055)

Если я пропущу часть отправки на сервер, код работает. Если я опускаю кодирование / декодирование, код работает. Сервер не делает ничего особенного, просто сохраняет полученный файл по определенному пути.

EncryptionUtility

package xxx;

import android.util.Base64;

import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.security.SecureRandom;

public class EncryptionUtility {

    //File encryption
    public static byte[] encryptData(SecretKey secretKey, byte[] data) throws Exception {
        SecureRandom secureRandom = new SecureRandom();
        byte[] iv = new byte[12];
        secureRandom.nextBytes(iv);

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);

        cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
        byte [] encryptedData = cipher.doFinal(data);

        ByteBuffer byteBuffer = ByteBuffer.allocate(4 + iv.length + encryptedData.length);
        byteBuffer.putInt(iv.length);
        byteBuffer.put(iv);
        byteBuffer.put(encryptedData);
        return byteBuffer.array();
    }

    //File decryption
    public static byte[] decryptData(SecretKey secretKey, byte[] encryptedData) throws Exception {
        ByteBuffer byteBuffer = ByteBuffer.wrap(encryptedData);
        int noonceSize = byteBuffer.getInt();

        if(noonceSize < 12 || noonceSize >= 16)
            throw new IllegalArgumentException("Nonce size is incorrect. Make sure that the incoming data is an AES encrypted file.");

        byte[] iv = new byte[noonceSize];
        byteBuffer.get(iv);

        byte[] cipherBytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(cipherBytes);

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);

        cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec);
        return cipher.doFinal(cipherBytes);
    }

    //Internal - SecretKey
    public static SecretKey generateSecretKey() {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128);
            return kgen.generateKey();
        }
        catch (Exception exc){
            exc.printStackTrace();
            return null;
        }
    }

    public static String parseSecretKeyToString(SecretKey secretKey){
        return Base64.encodeToString(secretKey.getEncoded(), 0);
    }
    public static SecretKey parseStringToSecretKey(String secretKeyString){
        try {
            return new SecretKeySpec(Base64.decode(secretKeyString, 0), 0, 16, "AES");
        }
        catch (Exception exc){
            return null;
        }
    }

}

Код шифрования

 SecretKey key = EncryptionUtility.generateSecretKey();
                String keyStr = EncryptionUtility.parseSecretKeyToString(key);
                fileBytes.put(param, EncryptionUtility.encryptData(key, readToBytes(file)));

Расшифровочный код

new AsyncTask<Void, Void, byte[]>(){
                @Override
                protected byte[] doInBackground(Void... voids) {
                    try {
                        URLConnection connection = new URL("urltovoicefile").openConnection();
                        InputStream inputStream = connection.getInputStream();
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();

                        int b;
                        while ((b = inputStream.read()) != -1){
                            baos.write(b);
                        }

                        byte[] result = baos.toByteArray();
                        return EncryptionUtility.decryptData(EncryptionUtility.parseStringToSecretKey(keyStr), result);
                    }
                    catch (Exception exc){
                        exc.printStackTrace();
                    }


                    return new byte[0];
                }

                @Override
                protected void onPostExecute(byte[] result) {
                    try {
                        File file = new File(activity.getCacheDir().toString(), "read.m4a");
                        FileOutputStream out = new FileOutputStream(file);
                        out.write(result);
                        out.close();

                        MediaPlayer mediaPlayer = new  MediaPlayer();
                        mediaPlayer.setDataSource(file.getAbsolutePath());
                        mediaPlayer.prepare();
                        mediaPlayer.start();
                    }
                    catch (Exception exc){
                        exc.printStackTrace();
                    }
                }
            }.execute();

EDIT: Загрузка байтового массива файла:

   /**
     * Adds a upload file section to the request
     */
    public void addFile(String fieldName, String fileName, byte[] fileBytes)
            throws IOException {
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append("Content-Disposition: form-data; name=\"" + fieldName
                + "\"; filename=\"" + fileName + "\"")
                .append(LINE_FEED);
        writer.append(
                "Content-Type: " + URLConnection.guessContentTypeFromName(fileName))
                .append(LINE_FEED);
        writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
        writer.append(LINE_FEED);
        writer.flush();

        outputStream.write(fileBytes);
        outputStream.flush();

        writer.append(LINE_FEED);
        writer.flush();
    }

// РЕДАКТИРОВАТЬ В ЭТОЙ ЧАСТИ КОДА БЫЛА ПРОБЛЕМА

/**
     * Completes the request and receives response from the server.
     * @return a list of Strings as response in case the server returned
     * status OK, otherwise an exception is thrown.
     */
    public String finish() throws IOException {
        String response;

        writer.append(LINE_FEED).flush(); //**THIS WAS ALREADY BEING ADDED BY uploadFile**
        writer.append("--" + boundary + "--").append(LINE_FEED);
        writer.close();

        int status = httpConn.getResponseCode();
        if (status == HttpURLConnection.HTTP_OK) {
            BufferedInputStream in = new BufferedInputStream(httpConn.getInputStream());
            response = inputStreamToString(in);

            httpConn.disconnect();
        }
        else
            throw new IOException("Server returned non-OK status: " + status);

        return response;
    }

Спасибо за любую помощь.

1 Ответ

0 голосов
/ 03 июля 2019

В итоге проблема была в моем инструменте для загрузки файлов.Я добавил CR / LF после каждого файла, а затем один дополнительный CR / LF в конце запроса.Удаление это решило проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...