Расшифровка данных, которые были зашифрованы AES с Objective-C с Java - PullRequest
4 голосов
/ 22 июня 2010

Я пытаюсь расшифровать данные, которые были изначально зашифрованы с помощью Objective-C в Java.

Есть другие вопросы, упоминающие об этом, но они действительно загромождены, и многие из них еще не решены, поэтому я опубликую свои собственные.

Это код, который шифрует данные:

  - (int) encryptWithKey: (NSString *) key
    {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char * keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
    bzero( keyPtr, sizeof(keyPtr) ); // fill with zeroes (for padding)

    // fetch key data
    [key getCString: keyPtr maxLength: sizeof(keyPtr) encoding: NSUTF8StringEncoding];

    // encrypts in-place, since this is a mutable data object
    size_t numBytesEncrypted = 0;
    CCCryptorStatus result = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
                                     keyPtr, kCCKeySizeAES128,
                                     NULL /* initialization vector (optional) */, 
                                     [self mutableBytes], [self length], /* input */
                                     [self mutableBytes], [self length]+32, /* output */
                                     &numBytesEncrypted );
    return numBytesEncrypted;
}

Я выполняю эту функцию и записываю полученные данные на диск с таким кодом:

NSString* strTest = @"Hallo Welt!";
NSLog(@"strTest = %@", strTest);

NSMutableData *protectedData = [NSMutableData dataWithData:[strTest dataUsingEncoding:NSUTF8StringEncoding]];

int laenge = [protectedData encryptWithKey:@"keykeykeykeykeykeykeykey"];

NSData* dataOutput = [[NSData alloc] initWithBytes:[protectedData bytes] length:laenge];


[dataOutput writeToFile:@"/encryptedFileObjC" atomically:YES];

В Java я использую этот код для достижения того же поведения:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
String keyString = "keykeykeykeykeykeykeykey";
byte[] keyBytes = keyString.getBytes("UTF-8");

cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, "AES"),
        new IvParameterSpec(new byte[16]));
byte[] resultBytes = cipher.doFinal("Hallo Welt!".getBytes("UTF8"));

FileOutputStream out =
        new FileOutputStream(new File("encryptedFileJava"));
out.write(resultBytes);
out.close();

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

Hallo Welt! зашифровано с помощью Java: 96 C5 CB 51 39 B5 27 FB B3 93 BF 92 18 BB 16 9B
Привет привет! зашифровано с помощью ObjC: A3 61 32 8E A5 E6 66 E0 41 64 89 25 62 D3 21 16

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

Мне нужно изменить код Java, чтобы получить тот же результат, что и код Objective-C, чтобы иметь возможность расшифровывать некоторые данные, которые были зашифрованы с помощью Objective-C.

Ответы [ 3 ]

2 голосов
/ 22 июня 2010
  1. Я бы не предположил, что CCCrypt поддерживает использование одного и того же массива для ввода и вывода. Попробуйте использовать два разных массива.
  2. Вы должны изменить размер выходного массива самостоятельно (numBytesEncrypted должен быть равен 16 после вызова).
  3. Насколько я вижу, нулевой IV сигнализирует с использованием ECB-шифрования вместо CBC. Пока ваш ввод меньше 15 байт, это не должно иметь никакого значения, но вы все равно должны это исправить.

РЕДАКТИРОВАТЬ: Другая проблема:

  1. Вы используете 24-байтовый ключ. AES-128 нужен 128-битный = 16-байтовый ключ, AES-192 нужен 192-битный = 24-байтовый ключ, а AES-256 - 256-битный = 32-байтовый ключ. Вы явно указываете AES-128 для CCCrypt, что означает, что он игнорирует последние 8 байтов ключа. Вы просто указываете AES для Java, что означает, что он смотрит на размер ключа, чтобы решить, какой вариант AES использовать. Поскольку вы предоставляете 24-байтовый ключ, он использует AES-192. Исправьте это так, чтобы оба конца использовали один и тот же алгоритм, и вы должны быть хорошими.
1 голос
/ 22 июня 2010

Это, вероятно, не способствует вашей проблеме, но в любом случае это неправильно:

   char * keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)

Это определяет массив kCCKeySizeAES128 + 1 указателей , а не kCCKeySizeAES128 + 1 байтКак это бывает, это нормально, потому что буфер, который вы получаете, в четыре или восемь раз больше, чем вам нужно, в зависимости от того, компилируете ли вы для 32 или 64 бит.

1 голос
/ 22 июня 2010

У вас потенциально есть куча проблем.

При выполнении любого шифрования / дешифрования вы должны убедиться:

  • строковое кодирование идентично (вы используете UTF8 в обоих,это хорошо)
  • схема заполнения идентична (у вас pkcs5 на одном и pkcs7 на другом)
  • вектор инициализации идентичен (у вас ноль на одном и пустые байты на другом)

.. и, конечно, схема шифрования идентична.Может показаться, что ваше шифрование использует AES128, хотя в комментариях обсуждается использование AES256.Не уверен, что версия Java использует

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...