AES-шифрование с Java на Python и наоборот - PullRequest
0 голосов
/ 21 мая 2019

Я пытаюсь зашифровать и расшифровать некоторую строку из python и java и наоборот, но у меня возникает проблема, когда я пытаюсь зашифровать в java и расшифровать в python с тем же ключом.

Вот мой алгоритм python для расшифровки вывода Java

from hashlib import pbkdf2_hmac
from Crypto.Cipher import AES
salt = bytes({0xC7, 0xB5, 0x99, 0xF4, 0x4B, 0x7C, 0x81, 0x77})
ITERATION_COUNT = 65536
KEY_LENGTH = 256
IV_LENGTH = 16
password = b'EKc8KyQj6H0pUe7WoGyU8MezojRvaDb9Uz1Ggu5fZ+c='
key = pbkdf2_hmac(
    hash_name='sha1',
    password=password,
    salt=salt,
    iterations=65536,
    dklen=32
)
plain="F7a45f2a2o7fi+mTn0DYAnkAOfkr1sW33S2kHBXGJV8eMU680qVz2a7MflE9ap8ztWaXIpHJmuYS98yPSnmQ+NZeLD5PQYU+nHwKarXFm+x7bJpF13e7SRmMIkHJuHl7KSKlrxz7fQjWj2gMooYNArmArGi/MiIOBZG9wT7qrYyUA/1twMlusw4EfqJdfo7dtro9XGlja8Ya1ZyuwFq/7sS+ni+Yd80mOAwmtkwUj9rKxJ51juVVek1n2SVO6a6phQmiy2K3fqMmc1xAKQj2trZaWT5MHAjjs6amNeZ1+1w/lQTLAn1pTYUdKOhYHgLDh63p1a3bVTXqslDvBkDFsY2PaXPWnzEqTF8vXiHOS542lWNKhPQusngRWugGai6C1goySV3w6UYNfoq6BfUzqRLYfkQb+qUS5RmTwEyb9AB4lsFfrskCB2mHklZTR+aqadE3Z7rrLkPZRUETbhq8LsDvxNJpr1ZDCKhIle79Dkqn6ZpvD6wiyokQaErhAVMVjXbppEJGv69SJHyLwyc+61JY42i05T57FsQWt30+bZ5rmC1fXV+sB8KvGjCDPGUT"
iv=plain[:IV_LENGTH]
cipher = AES.new(key, AES.MODE_CBC, iv )
print(cipher.decrypt(plain))

вывод должен выглядеть примерно так:

11101||11111011|1558523883103|10|https://staging................

Я пытаюсь преобразовать этот Java-код в код Python в зашифрованном виде и успешно расшифровать

import java.security.SecureRandom;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;


public class EncDec {
    private static final byte[] SALT = { (byte) 0xC7, (byte) 0xB5, (byte) 0x99,
            (byte) 0xF4, (byte) 0x4B, (byte) 0x7C, (byte) 0x81, (byte) 0x77 };
    private static final int ITERATION_COUNT = 65536;
    private static final int KEY_LENGTH = 256;
    private static final int IV_LENGTH = 16;
    private Cipher eCipher;
    private Cipher dCipher;
    private byte[] encrypt;
    private byte[] iv;

    public EncDec(String passPhrase) {
        try {
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT,ITERATION_COUNT, KEY_LENGTH);
            SecretKey secretKeyTemp = secretKeyFactory.generateSecret(keySpec);
            SecretKey secretKey = new SecretKeySpec(secretKeyTemp.getEncoded(),"AES");
            eCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            eCipher.init(Cipher.ENCRYPT_MODE, secretKey);
            dCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            iv = eCipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
            dCipher.init(Cipher.DECRYPT_MODE, secretKey,new IvParameterSpec(iv));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public EncDec(String passPhrase, String encryptedString) {
        try {
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT,ITERATION_COUNT, KEY_LENGTH);
            SecretKey secretKeyTemp = secretKeyFactory.generateSecret(keySpec);
            SecretKey secretKey = new SecretKeySpec(secretKeyTemp.getEncoded(),"AES");
            encrypt = Base64.decodeBase64(encryptedString);
            eCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            eCipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] iv = extractIV();
            dCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            dCipher.init(Cipher.DECRYPT_MODE, secretKey,new IvParameterSpec(iv));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public String encrypt(String encrypt) {
        String encStr = null;

        try {
            byte[] bytes = encrypt.getBytes("UTF8");
            byte[] encrypted = encrypt(bytes);
            byte[] cipherText = new byte[encrypted.length + iv.length];
            System.arraycopy(iv, 0, cipherText, 0, iv.length);
            System.arraycopy(encrypted, 0, cipherText, iv.length,encrypted.length);
            encStr = new String(Base64.encodeBase64(cipherText));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return encStr;
    }

    public byte[] encrypt(byte[] plain) throws Exception {
        return eCipher.doFinal(plain);
    }

    private byte[] extractIV() {
        byte[] iv = new byte[IV_LENGTH];
        System.arraycopy(encrypt, 0, iv, 0, iv.length);
        return iv;
    }

    public String decrypt() {
        String decStr = null;

        try {
            byte[] bytes = extractCipherText();

            byte[] decrypted = decrypt(bytes);
            decStr = new String(decrypted, "UTF8");
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return decStr;
    }

    private byte[] extractCipherText() {
        byte[] ciphertext = new byte[encrypt.length - IV_LENGTH];
        System.arraycopy(encrypt, 16, ciphertext, 0, ciphertext.length);
        return ciphertext;
    }

    public byte[] decrypt(byte[] encrypt) throws Exception {
        return dCipher.doFinal(encrypt);
    }

но я получаю неправильные данные:

b'\x8c\xb7m\xfc\x8b\x04\xc9s\xbbp\xe4\xd1\xafw\xb2A\x08\x01\xdb)\xd4qB\xe2\xef.........'

Также я не понимаю, что такое переменная SALT и для чего она используется? также как работает расчет IV параметра

...