Java - Python AES расшифровка шифрования - PullRequest
0 голосов
/ 13 июня 2019

У меня есть зашифрованный текст из Java (v8), использующий AES, который я пытаюсь расшифровать в python, используя тот же SecretKey, Salt, но у меня возникает проблема, когда я не пишу об индексе вне диапазона. Когда я делаю обратное, т. Е. Шифрую в python и дешифрую в java, я могу получить текст, но с некоторым нежелательным префиксом.

Ниже приведен мой код Java и Python, который я пробовал.

Java-код (Base64 от org.apache.commons.codec.binary.Base64)

public static String encrypt(String secretKey, String salt, String value) throws Exception {
        Cipher cipher = initCipher(secretKey, salt, Cipher.ENCRYPT_MODE);
        byte[] encrypted = cipher.doFinal(value.getBytes());
        return Base64.encodeBase64String(encrypted);
    }

    public static String decrypt(String secretKey, String salt, String encrypted) throws Exception {
        Cipher cipher = initCipher(secretKey, salt, Cipher.DECRYPT_MODE);
        byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
        return new String(original);
    }

    private static Cipher initCipher(String secretKey, String salt, int mode) throws Exception {

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");

        KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKeySpec skeySpec = new SecretKeySpec(tmp.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(mode, skeySpec, new IvParameterSpec(new byte[16]));
        return cipher;
    }

    public static void main(String[] args) throws Exception {
        String secretKey = "Secret";
        String fSalt = "tJHnN5b1i6wvXMwzYMRk";
        String plainText = "England";

        String cipherText = encrypt(secretKey, fSalt, plainText);
        System.out.println("Cipher: " + cipherText);
//      cipherText = "6peDTxE1xgLE4hTGg0PKTnuuhFC1Vftsd7NH9DF/7WM="; // Cipher from python
        String dcrCipherText = decrypt(secretKey, fSalt, cipherText);
        System.out.println(dcrCipherText);

    }

Python Code (версия 3.6) и Pycrypto V2.6

import base64
import hashlib
import os

from Crypto.Cipher import AES

BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)

# unpad = lambda s: s[:-ord(s[len(s) - 1:])]
unpad = lambda s: s[0:-s[-1]]

def get_private_key(secretKey, salt):
    key = hashlib.pbkdf2_hmac('SHA256', secretKey.encode(), salt.encode(), 65536, 32)
    return key


def encrypt(message, salt, secretKey):
    private_key = get_private_key(secretKey, salt)
    message = pad(message)
    iv = os.urandom(BS)  # 128-bit IV
    cipher = AES.new(private_key, AES.MODE_CBC, iv, segment_size=256)
    return base64.b64encode(iv + cipher.encrypt(message))


def decrypt(enc, salt, secretKey):
    private_key = get_private_key(secretKey, salt)
    enc = base64.b64decode(enc)
    iv = enc[:BS]
    cipher = AES.new(private_key, AES.MODE_CBC, iv, segment_size=256)
    return unpad(cipher.decrypt(enc[BS:]))


secretKey = "Secret"
salt = "tJHnN5b1i6wvXMwzYMRk"
plainText = "England"
cipher = encrypt(plainText, salt, secretKey)
print("Cipher: " + bytes.decode(cipher))

# cipher = "0JrZdg9YBRshfTdr1d4zwQ==" # Cipher from java
decrypted = decrypt(cipher, salt, secretKey)
print("Decrypted " + bytes.decode(decrypted))

Вывод Java расшифровывается: �U�����or���England когда я передаю шифр python, ожидается: England Выходные данные для расшифровки Python: unpad = lambda s : s[0:-s[-1]] IndexError: index out of range, ожидаемые: England

Я также просмотрел другую статью в стеке по этой проблеме, но она не сработала, поскольку они использовали другой режим.

1 Ответ

1 голос
/ 13 июня 2019

В python вы храните iv (вектор инициализации) в первых 16 байтах зашифрованного сообщения.

В Java вы ничего такого не делаете - вы пропускаете пустой IV и обрабатываете все сообщение, включая первые 16 байтов, как зашифрованный текст.

Вам необходимо убедиться, чтоJava и Python совпадают.

Либо вы не используете IV в обоих случаях, в этом случае вы удаляете эту часть в Python.

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

...