128-битное шифрование AES CBC с использованием Java и PHP

Недавно я использовал алгоритм AES CBC 128 в Java для шифрования данных. Теперь мне нужно перестроить этот алгоритм в PHP, но я понятия не имею, как, потому что алгоритмы PHP в Интернете дают разные результаты. Возможно ты можешь помочь мне.

Это Java-код для шифрования:

private SecretKeySpec secretKey;
private IvParameterSpec ivSpec;

public void setKey(String myKey) {
    MessageDigest sha = null;
    try {
        byte[] key = myKey.getBytes("UTF-8");
        sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16);
        secretKey = new SecretKeySpec(key, "AES");

        byte[] iv = new String("1010101010101010").getBytes("UTF-8");
        ivSpec = new IvParameterSpec(iv);

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

public String encrypt(String strToEncrypt) {
    try {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
        return Base64.encode(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public String decrypt(String strToDecrypt) {
    try {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        return new String(cipher.doFinal(Base64.decode(strToDecrypt)));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public static void main(String[] args) {

    AESText aes = new AESText();
    final String secretKey = "com.secure.test.projectjasdS/FjkGkGhkGjhG786Vjfg=tjGFGH";
    aes.setKey(secretKey);

    String originalString = "test set se ts et set s et se";
    String encryptedString = aes.encrypt(originalString);
    String decryptedString = aes.decrypt(encryptedString);

    System.out.println("origin: " + originalString);
    System.out.println("encrypted: " + encryptedString);
    System.out.println("decrypted: " + decryptedString);
}

Это мой php код:

    protected $key;
    protected $method = 'AES-128-CBC';
    protected $iv = '1010101010101010';
    protected $option = OPENSSL_CIPHER_AES_128_CBC;

    function __construct($key)
    {
        $this->key = $key;
    }

    public function encrypt($data) {
        if (is_null($data)) {
            return "Error " . INVALID_PARAMS_ENCRYPTIONS . ": Data is null ";
        }
        $enc = openssl_encrypt($data, $this->method, $this->key, $this->option, $this->iv);
        return base64_encode($enc);
    }

    public function decrypt($data) {
        if (is_null($data)) {
            return "Error " . INVALID_PARAMS_ENCRYPTIONS . ": Data is null ";
        }
        $data = base64_decode($data);
        $dec = openssl_decrypt($data, $this->method, $this->key, $this->option, $this->iv);
        return $dec;
    }

Когда я зашифровал данные из Java-шифрования, этот результат не может быть расшифрован при расшифровке Php.

Ребята, можете ли вы помочь мне с созданием сценария PHP, который возвращает те же результаты с Java-шифрованием?

1 ответ

Решение

На первый взгляд я вижу здесь три проблемы:

Во-первых: вы не используете тот же режим: в Java у вас есть AES/ECB/PKCS5Padding тогда как ваш PHP использует AES-128-CBC,

Второе: вы, вероятно, не используете одни и те же IV в коде Java и PHP (IV не имеют значения для ECB, но как только вы переключите Java на CBC, он вам понадобится):

У тебя есть $iv = '1010101010101010' (который затем передается openssl) в вашем PHP, но ничего подобного в вашей Java.

По крайней мере, вам, вероятно, понадобится нечто подобное и в вашей Java-части:

cipher.init(Cipher.DECRYPT_MODE/ENCRYPT_MODE, secretKey, new IvParameterSpec(iv))

с iv быть byte[] содержащий ваши IV байты.

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

редактирование: четвертое: еще одна проблема заключается в том, как вы получаете ключевые биты, которые будут использоваться. В java вы берете первые 16 байтов sha1-хеша, а в php вы просто передаете $key в openssl. openssl может получить ключ шифрования другим способом.


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

Другие вопросы по тегам