Локальное шифрование и дешифрование данных - PullRequest
0 голосов
/ 29 октября 2018

Здравствуйте, дорогие люди из stackoverflow,

В настоящее время я разрабатываю / внедряю меры безопасности в своем приложении и испытываю некоторые проблемы с шифрованием и дешифрованием определенных данных.

Вчера фактически я смог зашифровать сообщение, а затем расшифровать зашифрованное сообщение тем же экземпляром класса - но не смог сделать наоборот. Это то, что я хотел опубликовать сегодня (о проблеме) -

После отправки последних изменений из системы Linux, с которой я работал, и попытки продолжить работу на компьютере с Windows, была выдана следующая ошибка:

    java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1026)
    at javax.crypto.Cipher.implInit(Cipher.java:801)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
    at javax.crypto.Cipher.init(Cipher.java:1249)
    at javax.crypto.Cipher.init(Cipher.java:1186)
    at com.x.backend.security.Decrypter.encrypt(Decrypter.java:43)
    at crypto.CryptoTest.main(CryptoTest.java:11)
java.lang.NullPointerException
    at javax.crypto.spec.IvParameterSpec.<init>(IvParameterSpec.java:53)
    at com.x.backend.security.Decrypter.decrypt(Decrypter.java:54)
    at crypto.CryptoTest.main(CryptoTest.java:12)

Итак, я попытался найти решение, но не нашел, поэтому вот что я попробовал:

  • Обновление до JDK 9/10/11 для меня не вариант, я попробовал это, я потерпел неудачу, и было бы слишком много, чтобы приспособиться, если бы я поднялся (это не стоит усилия на данный момент)

  • Я читал кое-что о Java Cryptography Extension (JCE), но это не относится ко мне, так как я использую версию JDK 1.8.66 (а с 1.8.55 его нет больше требуется любой тип файла, установленного в каталоге java)

  • Недействительный кеш (IntelliJ) + Перезагрузка моего компьютера

  • Сброс состояния проекта до первоначального коммита (git hard reset)

Мой класс:

public class Decrypter {

    private static Decrypter instance;

    private Cipher cipher;

    private byte[] IV;

    private SecretKeySpec secretKeySpec;

    private Decrypter() {
        initialize();
    }

    private void initialize() {
        try {
            final byte[] salt = "@1jq3#-o1_uHvaL:".getBytes();
            final String key = "hehexd";
            final int iterationCount = 12;
            final int keyStrength = 256;
            this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            this.secretKeySpec = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(new PBEKeySpec(key.toCharArray(), salt, iterationCount, keyStrength)).getEncoded(), "AES");
        } catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    public final String encrypt(String data) {
        try {
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            IV = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
            return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public final String decrypt(String base64EncryptedData) {
        try {
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(IV));
            byte[] decryptedData = Base64.getDecoder().decode(base64EncryptedData);
            byte[] utf8 = cipher.doFinal(decryptedData);
            return new String(utf8, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static Decrypter getInstance() {
        return instance == null ? instance = new Decrypter() : instance;
    }
}

Мой тестовый класс:

    public class CryptoTest {

    public static void main(String[] args) {
        String encrypted = Decrypter.getInstance().encrypt("lol");
        String decrypted = Decrypter.getInstance().decrypt(encrypted);
        System.out.println("Verification: PLAINTEXT -> ENCRYPT: " + encrypted);
        System.out.println("Verification: ENCRYPT -> DECRYPT: " + decrypted);
    }
}

Пожалуйста, не возражайте против любой обычной ошибки / плохой практики, я новичок, когда дело доходит до криптографии (читая мой путь к этому с этого момента)

Любая помощь или вклад будут оценены!

Edit:

Спасибо за ваши немедленные ответы!

К сожалению, у меня появляется другая ошибка. Полный вывод:

    Verification: PLAINTEXT -> ENCRYPT: 
java.security.InvalidKeyException: Illegal key size
Verification: PLAINTEXT -> DECRYPT: 
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
    at javax.crypto.Cipher.implInit(Cipher.java:805)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
    at javax.crypto.Cipher.init(Cipher.java:1396)
    at javax.crypto.Cipher.init(Cipher.java:1327)
    at com.x.backend.security.Decrypter.encrypt(Decrypter.java:48)
    at crypto.CryptoTest.main(CryptoTest.java:11)
java.security.InvalidKeyException: No installed provider supports this key: javax.crypto.spec.SecretKeySpec
    at javax.crypto.Cipher.chooseProvider(Cipher.java:893)
    at javax.crypto.Cipher.init(Cipher.java:1396)
    at javax.crypto.Cipher.init(Cipher.java:1327)
    at com.x.backend.security.Decrypter.decrypt(Decrypter.java:58)
    at crypto.CryptoTest.main(CryptoTest.java:12)

измененный код:

 public final String encrypt(String data) {
        try {
            IV = new IvParameterSpec("testtesttesttest".getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, IV);
            return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Оказывается, обновление до последней версии JDK исправило все возникшие проблемы. Теперь я легко могу расшифровать и зашифровать вещи самостоятельно!

Спасибо всем, кто участвовал в поиске решения!

0 голосов
/ 29 октября 2018

Я не знаю, откуда у вас информация, что JDK 1.8.66 поставляется с неограниченной силой JCE. Это не так за пределами США.

Вам все еще нужно загрузить и установить JCE-файлы неограниченной силы из Oracle .

Если вы уверены, у вас неограниченная сила JCE, попробуйте добавить к jre/lib/security/java.security:

crypto.policy=unlimited

Только начиная с Java SE 8u161 неограниченная сила включена по умолчанию. Так что эта настройка там не нужна.


С другой стороны - ваша обработка ошибок может быть улучшена. Лучше заменить e.printStackTrace() на throw new RuntimeException(e), чтобы все эти ошибки инициализации рассматривались как фатальные (они являются прерывателем сделки на этом этапе).

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