Подтвердить что ты не робот

Разница AES между iPhone (Objective-c) и Java

Я весь день рвал мои волосы, пытаясь решить это...

У меня есть клиент objective-c, работающий на iPhone, подключающийся к серверу Java. IPhone шифрует данные с помощью AES, но я не могу их расшифровать на сервере. Я использую известную кодовую фразу и сообщение (одиночную строку) и создаю массив байтов на iPhone, создавая массив байтов сравнения на сервере Java с использованием одного и того же ключа и сообщения, но массивы байтов совершенно разные (и, следовательно, не могут декодироваться на стороне Java).

Клиент использует библиотеку CommonCrypto со следующими настройками...

Данные NSData содержат слово "сообщение", используя dataUsingEncoding:NSASCIIStringEncoding Ключ - это NSData, в котором снова используется фраза "1234567891123456" с использованием кодировки, как указано выше. Алгоритм kCCAlgorithmAES128 Параметры kCCOptionsPKCS7Padding (что, на мой взгляд, соответствует ЕЦБ на сервере?!)

Сервер использует следующий код...

byte[] key = "1234567891123456".getBytes();
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");

SecretKeySpec k =  new SecretKeySpec(key, "AES");
c.init(Cipher.ENCRYPT_MODE, k);
byte[] encryptedData = c.doFinal("message".getBytes());

НО данные в encryptedData не совпадают с данными, которые генерируются в коде objective-c, байт-массивы совершенно разные.

Может ли кто-нибудь увидеть что-нибудь очевидное, я делаю неправильно? Я думаю, что настройки все одинаковые...: (

  • ОБНОВЛЕНИЕ - по запросу....

Хорошо, так вот идет....

Клиент iPhone шифрует следующую строку "message" Он использует ключ "1234567891123456" Он использует вектор инициализации "1010101010101010" Он использует AES128, с режимом CBC (насколько я могу судить) и опциями kCCOptionsPKCS7Padding.

Результатом шифрования (с кодировкой base64) является UHIYllDFAXl81ZM7OZPAuA ==

Сервер шифрует одну и ту же строку с тем же ключом и вектором инициализации. Он использует следующий Cipher.getInstance( "AES/CBC/PKCS5Padding" );

Результатом шифрования (с кодировкой base64) является ALBnFIHysLbvAxjvtNo9vQ ==

Спасибо.

  • ОБНОВЛЕНИЕ 2 - В соответствии с запросом...

Вот код iPhone....

NSData *toencrypt = [@"message" dataUsingEncoding:NSASCIIStringEncoding];

NSData *pass = [@"1234567891123456" dataUsingEncoding:NSASCIIStringEncoding];

NSData *iv = [@"1010101010101010" dataUsingEncoding:NSASCIIStringEncoding];    

CCCryptorStatus status = kCCSuccess;

NSData *encrypted = [toencrypt dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status];

NSString *text = [NSString base64StringFromData:encrypted length:[encrypted length]];

Ниже приведена категория NSData для шифрования...

http://github.com/AlanQuatermain/aqtoolkit/tree/master/CommonCrypto/

Кстати, я проверил массивы байтов, которые находятся в toencrypt, pass и iv, и они соответствуют тем, которые находятся на сервере.

4b9b3361

Ответ 1

Это не моя область, но на вашем клиенте у вас есть PKCS7, но на сервере у вас есть PKCS5.

Ответ 2

Я просто столкнулся с одной и той же проблемой. Я использую CommonCrypto на iOS-клиенте, используя настройки:

NSData * encrypted = [data dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status];

Сервер использует Cipher.getInstance("AES/CBC/PKCS5Padding"); с тем же ключом и вектором инициализации, что и клиент.

После того, как я ударил головой о стену в течение последних нескольких часов, я, наконец, последовал совету Джейсона и проверил процедуру dataEncryptedUsingAlgorithm и распечатал keyData сразу после FixKeyLengths. Оказывается, мой 128-битный ключ был расширен до 192 бит с добавлением 0s к концу. После исправления все работает правильно.:)

Обновление: мой ответ был опубликован почти 2 года назад, и эта проблема, похоже, исправлена ​​в последнем NSData+CommonCrypto коде. В частности, это вызвало эту проблему:

static void FixKeyLengths( CCAlgorithm algorithm, NSMutableData * keyData, NSMutableData * ivData )
{
  NSUInteger keyLength = [keyData length];
  switch ( algorithm )
  {
    case kCCAlgorithmAES128:
    {
      if ( keyLength <= 16 )
      {
        [keyData setLength: 16];
      }
      else if ( keyLength <= 24 )
      {
        [keyData setLength: 24];
      }
      else
      {
        [keyData setLength: 32];
      }

      break;
    }

Первая проверка keyLength <= 16 раньше не была.

Если вы все еще испытываете проблемы сейчас, возможно, что-то еще.

Ответ 3

В каком режиме используется iPhone с AES? Вы ничего не перечисляете, поэтому, возможно, это означает, что он не использует цепочку (ECB).

Однако на стороне Java вы используете CBC, но не указываете вектор инициализации. Это определенно неправильно. Если вы действительно используете CBC, вы должны иметь IV, который использовался во время шифрования. IV не секрет; он может быть отправлен вместе с зашифрованным текстом.

Если вы действительно используете ECB, нет IV, но ваша Java указывает неправильный режим.

Ответ 4

На основе ваших образцов сервер делает это правильно, а клиент - нет.

Глядя на данные, я бы предположил, что ключ неправильный. Пожалуйста, покажите нам код iPhone, особенно код, чтобы перейти от "1234567891123456" к вашему ключу.

Ответ 5

Недавно я встретил это в другом проекте. Проблема заключалась в том, что ключ был слишком длинным, чтобы вписаться в буфер char внутри метода dataEncryptedUsingAlgorithm.

Проблема заключалась в том, что метод getBytes на NSString был мягким. Он скопировал бы большую часть строки в буфер, но после того, как ключ был слишком длинным, он "пометил" операцию как потерю неудачи, установив первый char в NUL (char 0).

Вставьте этот метод в Xcode и посмотрите, как выглядит ваш буфер char [16]. Он может иметь эту же проблему и иметь содержимое { 0, '2', '3', '4', ... }.