AES разница между iPhone (Objective-c) и Java - PullRequest
16 голосов
/ 28 октября 2009

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

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

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

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

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

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 не совпадают с данными, генерируемыми в коде target-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, и они соответствуют тем, которые находятся на сервере.

Ответы [ 5 ]

3 голосов
/ 25 октября 2011

Я только что столкнулся с точно такой же проблемой. Я использую 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-битного с добавлением нуля в конце. После исправления все работает нормально. :)

Обновление: мой ответ был опубликован почти 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 голосов
/ 28 октября 2009

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

2 голосов
/ 28 октября 2009

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

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

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

0 голосов
/ 22 июня 2010

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

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

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

0 голосов
/ 29 октября 2009

Судя по вашим примерам, сервер делает все правильно, а клиент - нет.

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

...