Расшифровка зашифрованной строки CommonCrypto в кодировке Base 64 в Java (AES / CBC / PKCS7Padding) - PullRequest
0 голосов
/ 30 июня 2018

Я пытаюсь расшифровать String с помощью известного ключа в Java, используя стандартный Cipher API.

Зашифрованный String поступает из Web Service с использованием стандартной библиотеки CommonCrypto, которая responds с некоторыми statistics в качестве зашифрованных строк через равные промежутки времени.

Спецификации AES/CBC/PKCS7Padding с KeySize = 32 Bytes и BlockSize = 16 Bytes и Encoding UTF-8 (raw) & Base64. Я намереваюсь написать Java-клиент, который может запросить эти statistics, decrypt и сохранить их для последующего анализа.

Вопрос 1. Может ли CommonCrypto автоматически дополнять клавиши дополнительными символами, если клавиша короткая? Например, меньше чем 16 Bytes or 32 Bytes.

Вопрос 2. Какие меры кодирования я должен предпринять, чтобы идентичные encryption/decryption на обоих концах?

Примеры строк и ключей

String message = "mQp9sp8ri1E0V1Xfso1d5g==Mrf3wtaqUjASlZmUO+BI8MrWsrZSC0MxxMocswfYnqSn/VKB9luv6E8887eCxpLNNAOMB0YXv6OS7rFDFdlvC53pCHo3cVZiLJFqgWN/eNiC9p4RMxyFCcOzWrwKzT5P8sy55DwE25DNJkvMthSaxK5zcP1OdLgBiZFOSxYRsX4rBk7VP7p5xr2uTGjRL+jmGgB9u3TmeCNCr8NxGLNt6g==";
String userKey = "123456789";

private static String decrypt (String message, String userKey) throws UnsupportedEncodingException,
            NoSuchPaddingException,
            NoSuchAlgorithmException,
            InvalidKeyException,
            ShortBufferException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, NoSuchProviderException {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        if (message.length() >= 48) {

        ivFromEncryptedString = message.substring(0, Math.min(message.length(), 24));
        messageFromEncryptedString = message.substring(24, message.length());

        System.out.println(ivFromEncryptedString);
        System.out.println(messageFromEncryptedString);

        byte[] data = decodeBase64(messageFromEncryptedString);
        byte[] ivData = decodeBase64(ivFromEncryptedString);

        paddedKey = padShortKeys(userKey);

        byte[] keyBytes = paddedKey.getBytes(CHARSET);

        MessageDigest sha = MessageDigest.getInstance("SHA-256"); //key
        keyBytes = sha.digest(keyBytes);

        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivData);
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);

            byte [] encrypted = new byte[cipher.getOutputSize(data.length)];
            int ctLength = cipher.update(data, 0, data.length, encrypted, 0);
            ctLength += cipher.doFinal(encrypted, ctLength);
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            return encrypted;
        }
    }
    return null;
    }
private static String encodeBase64(byte [] in){
    return Base64.getEncoder().encodeToString(in);
}

private static byte[] decodeBase64(String str) throws UnsupportedEncodingException {
    return DatatypeConverter.parseBase64Binary(str);
}

Также с текущим статусом кода я получаю символы-заполнители вместо желаемого результата.

Заранее спасибо, ребята. :)

1 Ответ

0 голосов
/ 02 июля 2018

CommonCrypto неясно, какую реализацию вы используете? Apple, Apache, Java Class Cipher или другой, укажите ссылку на него.

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

  2. Обычно, если зашифрованные данные должны быть выражены в виде строки символов, используется кодировка Base64.

Как утверждает Джеймс, для одноразового шифрования просто используйте doFinal(ByteBuffer input, ByteBuffer output), который шифрует или дешифрует данные в одной операции.

Примечание: 9-значный ключ имеет только около 33-битной защиты, что недостаточно близко. Простого использования хеш-функции недостаточно для получения ключа шифрования из пароля, вместо этого следует использовать PBKDF2 или Argon2 .

...