Шифрование взаимодействия между Java (Cipher) и JavaScript (crypto-js) - PullRequest
0 голосов
/ 11 сентября 2018

Мне было поручено исправить алгоритм межсайтового шифрования, который прекрасно работал раньше, но внезапно потерял самообладание по неизвестным причинам, никто не трогал код для обоих языков (Java & JS).

Я не очень хорошо разбираюсь в криптографии, поэтому не знаю, какие возможные решения нужно искать или работать с ними.В основном задача состояла в том, чтобы этот код шифрования на Java был переведен в JavaScript, который имел бы обе строки Base64, которые должны были быть дешифрованы с помощью Java.

Ниже приведены фрагменты кода дляшифрование выполняется с помощью Java & JS и процесс расшифровки на Java:

Шифрование Java

public static String encryptMsg(String message) {
    @SuppressLint("GetInstance") Cipher cipher = null;
    try {
        cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        byte[] cipherText = cipher.doFinal(message.getBytes(UTF_CHARSET));
        return Base64.encodeToString(cipherText, Base64.DEFAULT);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
        e.printStackTrace();
    } catch (NullPointerException e) {
        //Do nothing, nothing to encrypt
    }
    return null;
}

Шифрование JavaScript

function encryptData(data, key) {
 const options = {
  mode: Crypto.mode.ECB,
  padding: Crypto.pad.Pkcs7
 }
 const secret = Crypto.enc.Utf8.parse(key)
 const encrypted = Crypto.AES.encrypt(data, secret, options)
 return encrypted.ciphertext.toString(Crypto.enc.Base64)
}

Расшифровка Java

public static String decryptMsg(String base64cipherText) {
    @SuppressLint("GetInstance") Cipher cipher = null;
    try {
        cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, secret);
        String decryptString = new String(cipher.doFinal(Base64.decode(base64cipherText, Base64.DEFAULT)), UTF_CHARSET);
        return decryptString;
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
        e.printStackTrace();
    } catch (NullPointerException e) {
        //Do nothing, nothing to decrypt
    }
    return null;
}

В настоящее время результаты возвращают null в зашифрованной строке с использованием функции шифрования JavaScript при расшифровке, поэтому, вероятно, шифрование выполняется правильно (?) Я не уверен, что я здесь упускаю или делаю неправильно ...

1 Ответ

0 голосов
/ 11 сентября 2018

Кажется, вам не хватает IV (вектор инициализации).

на самом деле не знаю, что такое IV или, если он нужен здесь, код Java для шифрования нигде не говорит об этом

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

Я не уверендля JavaScript API, но, по крайней мере, я могу привести пример на Java.Также вы можете взглянуть на мой блог о криптографических примерах

Java Encryption

 SecureRandom rnd = new SecureRandom();
 byte[] iv = new byte[SYMMETRIC_BLOCK_SIZE / 8];
 IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
 SecretKey symmetricKey = new SecretKeySpec(encryptionParams.getKey(), SYMMETRIC_KEY_ALG);

Cipher cipher = Cipher.getInstance(SYMMETRIC_CIPHER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, symmetricKey, ivParamSpec);

byte[] encrypted = cipher.doFinal(encryptionParams.getPlaintext());
/* and encoded form can contain form of base64( IV + ciphertext )  */

Для режима CBC IV должен быть случайным,Если вы не укажете параметр IVParameter, он будет сгенерирован, и вы можете прочитать его с cipher.getIV();.IV может быть общедоступным, его обычно предшествуют зашифрованному тексту, поскольку IV необходим для дешифрования самого зашифрованного текста.

Расшифровка Java

/* if IV is prepended before the ciphertext, it can be fetched as sub-array
  of the decoded message */
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);

Cipher cipher = Cipher.getInstance(SYMMETRIC_CIPHER_NAME);
cipher.init(Cipher.DECRYPT_MODE, symmetricKey, ivParamSpec);

byte[] decrypted = cipher.doFinal(encryptionParams.getCiphertext());

В этомНапример, нет Mac (включая код аутентификации сообщений), вы можете взглянуть на связанный пример.

Для JavaScript вы должны взглянуть на используемый API, но принцип остается тем же (вы должны сгенерировать, использовать, передать и предоставить IV тоже как-то). Этот блог содержит более полный код.

var iv = CryptoJS.lib.WordArray.random(128/8);
var encrypted = CryptoJS.AES.encrypt(msg, key, { 
  iv: iv, 
  padding: CryptoJS.pad.Pkcs7,
  mode: CryptoJS.mode.CBC
});
...