AES: Не дешифруется строка

349
02 февраля 2017, 00:42

У меня есть две функции, encrypt и decrypt. В encrypt я создаю ключ, шифрую строку и добавляю в начало строки сам ключ. В decrypt сначала отделяю ключ от зашифрованной строки(размер ключа фиксированный) и пытаюсь расшифровать, при этом результат не совпадает с начальной строкой, что и является проблемой.

Проверил в дебаге, массив key при вызове decrypt(encrypt(string)) в обеих функциях одинаковый, видимо проблема в SecretKeySpec(имхо).

Как можно исправить?

Сам код:

static String encrypt(String str) {
    SecretKeySpec sks = null;
    byte[] key = null;
    try {
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed("this is seed".getBytes());
        KeyGenerator kg = KeyGenerator.getInstance("AES");
        kg.init(128, sr);
        key = kg.generateKey().getEncoded();
        sks = new SecretKeySpec(key, "AES");
    } catch (Exception e) {
        Log.e("Crypto", "AES secret key spec error");
    }
    // Encode the original data with AES
    byte[] encodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.ENCRYPT_MODE, sks);
        encodedBytes = c.doFinal(str.getBytes());
    } catch (Exception e) {
        Log.e("Crypto", "AES encryption error");
    }
    return Base64.encodeToString(key, Base64.DEFAULT) + 
        Base64.encodeToString(encodedBytes, Base64.DEFAULT);
}
static String decrypt(String str) {
    byte[] key = Base64.decode(str.substring(0, 25), Base64.DEFAULT);
    byte[] strBytes =
        Base64.decode(str.substring(25, str.length()), Base64.DEFAULT);
    SecretKeySpec sks = new SecretKeySpec(key, "AES");
    // Decode the encoded data with AES
    byte[] decodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.DECRYPT_MODE, sks);
        decodedBytes = c.doFinal(strBytes);
    } catch (Exception e) {
        Log.e("Crypto", "AES decryption error");
    }
    return Base64.encodeToString(decodedBytes, Base64.DEFAULT);
}

UPD Вызов методов:

editText.setText(Crypt.encrypt(editText.getText().toString()));
...
editText.setText(Crypt.decrypt(editText.getText().toString()));
Answer 1

Проблема у вас в не в ключе, а в лишнем кодировании при возврате строки.

Проще всего такой код отлаживать на JVM при помощи тестов.

// этот тест для обычного JUnit
// я не пробовал запускать его на андроиде
@Test
public void encrypt() throws Exception {
    String cryptoText = AES.encrypt("test");
    String plainText = AES.decrypt(cryptoText);
    assertThat(plainText, is("test"));
}
static String encrypt(String str) {
    SecretKeySpec sks = null;
    byte[] key = null;
    try {
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed("this is seed".getBytes());
        KeyGenerator kg = KeyGenerator.getInstance("AES");
        kg.init(128, sr);
        key = kg.generateKey().getEncoded();
        sks = new SecretKeySpec(key, "AES");
    } catch (Exception e) {
        Log.e("Crypto", "AES secret key spec error");
    }
    // Encode the original data with AES
    byte[] encodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.ENCRYPT_MODE, sks);
        encodedBytes = c.doFinal(str.getBytes());
    } catch (Exception e) {
        Log.e("Crypto", "AES encryption error");
    }
    // я добавил длину ключа и разделитель
    String encodeKey = Base64.encodeToString(key, Base64.DEFAULT);
    return encodeKey.length() + "$" + encodeKey +
        Base64.encodeToString(encodedBytes, Base64.DEFAULT);        
}
static String decrypt(String str) {
    int pos = str.indexOf("$");
    int keyLength = Integer.valueOf(str.substring(0, pos));
    int keyStart = pos + 1;
    byte[] key = Base64.decode(str.substring(keyStart, keyStart + keyLength), Base64.DEFAULT);
    int dataStart = keyStart + keyLength;
    byte[] strBytes =
        Base64.decode(str.substring(dataStart, str.length()), Base64.DEFAULT);
    SecretKeySpec sks = new SecretKeySpec(key, "AES");
    // Decode the encoded data with AES
    byte[] decodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.DECRYPT_MODE, sks);
        decodedBytes = c.doFinal(strBytes);
    } catch (Exception e) {
        Log.e("Crypto", "AES decryption error");
    }
    // Base64 не надо, так как у вас там просто строка
    // return Base64.encodeToString(decodedBytes, Base64.DEFAULT);
    return new String(decodedBytes);
}
READ ALSO
Разница между методом по умолчанию в интерфейсе и обычным методом в классе

Разница между методом по умолчанию в интерфейсе и обычным методом в классе

Чем отличаются между собой метод по умолчанию, объявленный в интерфейсе с модификатором default и обычный метод, объявленный в обычном классе?

357
Android studio графика .xml

Android studio графика .xml

Полазив в anroid studio я нашел файлы векторной графики в (данном случаи это были иконки, в форматеxml)

400
общие вопросе по системе координат в JavaFX

общие вопросе по системе координат в JavaFX

я тут начал писать программу в javafx и у меня скопилось много вопросов по поводу координат в инете я нечего не нашел

424