Функция шифрования для функции шифрования Crypto Js - PullRequest
1 голос
/ 14 апреля 2020

У меня есть следующий код, который был скопирован из правильного ответа здесь :

public static String decrypt(String cipherText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        byte[] cipherData = Base64.getDecoder().decode(cipherText);
        byte[] saltData = Arrays.copyOfRange(cipherData, 8, 16);

        MessageDigest md5 = MessageDigest.getInstance("MD5");
        final byte[][] keyAndIV = generateKeyAndIV(32, 16, 1, saltData, secret.getBytes(StandardCharsets.UTF_8), md5);
        SecretKeySpec key = new SecretKeySpec(keyAndIV[0], "AES");
        IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);

        byte[] encrypted = Arrays.copyOfRange(cipherData, 16, cipherData.length);
        Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
        aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
        byte[] decryptedData = aesCBC.doFinal(encrypted);
        String decryptedText = new String(decryptedData, StandardCharsets.UTF_8);

        return decryptedText;
    }

Как мне написать функцию шифрования для этого в Java? Я пробовал что-то вроде этого, но это не работает:

public static String encrypt(String plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        final byte[][] keyAndIV = generateKeyAndIV(32, 16, 1, getNextSalt(), secret.getBytes(StandardCharsets.UTF_8), md5);
        SecretKeySpec skeySpec = new SecretKeySpec(keyAndIV[0], "AES");
        IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(plainText.getBytes());

        return Base64.getEncoder().encodeToString(encrypted);
    }

    public static byte[] getNextSalt() {
        byte[] salt = new byte[8];
        RANDOM.nextBytes(salt);
        return salt;
    }

1 Ответ

1 голос
/ 14 апреля 2020

Метод encrypt должен возвращать данные в формате OpenSSL, который состоит из ASCII-кодировки Salted __ , за которым следуют 8-байтовая случайно сгенерированная соль и фактический зашифрованный текст, в результате чего данные являются Base64 закодированы после их объединения.

Обратите внимание, однако, что функция получения ключа, используемая для формата OpenSSL, небезопасна и не является стандартом, здесь . Возможное расширение метода encrypt может быть:

public static String encrypt(String plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {

    byte[] salt =  getNextSalt();
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    final byte[][] keyAndIV = generateKeyAndIV(32, 16, 1, salt, secret.getBytes(StandardCharsets.UTF_8), md5);
    SecretKeySpec skeySpec = new SecretKeySpec(keyAndIV[0], "AES");
    IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
    byte[] encrypted = cipher.doFinal(plainText.getBytes());

    byte[] prefix = "Salted__".getBytes(StandardCharsets.US_ASCII);
    byte[] prefixSaltEncrypted = new byte[prefix.length + salt.length + encrypted.length];
    System.arraycopy(prefix, 0, prefixSaltEncrypted, 0, prefix.length);
    System.arraycopy(salt, 0, prefixSaltEncrypted, prefix.length, salt.length);
    System.arraycopy(encrypted, 0, prefixSaltEncrypted, prefix.length + salt.length, encrypted.length);

    return Base64.getEncoder().encodeToString(prefixSaltEncrypted);
}
...