Как я могу сделать свое шифрование AES идентичным между Java и Objective-C (iPhone)?

Я шифрую строку в объекте-с, а также шифрую одну и ту же строку на Java с помощью AES, и вижу некоторые странные проблемы. Первая часть результата соответствует некоторой точке, но тогда она отличается, поэтому, когда я иду на декодирование результата Java на iPhone, он не может ее расшифровать.

Я использую строку источника «Теперь, и что это за глупость. Знаете ли вы?» Используя ключ «1234567890123456»,

Целевой код-код для шифрования следующий: ПРИМЕЧАНИЕ: это категория NSData, поэтому предположим, что метод вызывается в объекте NSData, поэтому «self» содержит данные байта для шифрования.

- (NSData *)AESEncryptWithKey:(NSString *)key { 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]; NSUInteger dataLength = [self length]; //See the doc: For block ciphers, the output size will always be less than or //equal to the input size plus the size of one block. //That's why we need to add the size of one block here size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES128, NULL /* initialization vector (optional) */, [self bytes], dataLength, /* input */ buffer, bufferSize, /* output */ &numBytesEncrypted); if (cryptStatus == kCCSuccess) { //the returned NSData takes ownership of the buffer and will free it on deallocation return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); //free the buffer; return nil; } 

И код шифрования java

 public byte[] encryptData(byte[] data, String key) { byte[] encrypted = null; Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); byte[] keyBytes = key.getBytes(); SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); try { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); 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) { logger.log(Level.SEVERE, e.getMessage()); } finally { return encrypted; } } 

Шестигранный вывод кода объектива-c –

 7a68ea36 8288c73d f7c45d8d 22432577 9693920a 4fae38b2 2e4bdcef 9aeb8afe 69394f3e 1eb62fa7 74da2b5c 8d7b3c89 a295d306 f1f90349 6899ac34 63a6efa0 

и выход java –

 7a68ea36 8288c73d f7c45d8d 22432577 e66b32f9 772b6679 d7c0cb69 037b8740 883f8211 748229f4 723984beb 50b5aea1 f17594c9 fad2d05e e0926805 572156d 

Как вы можете видеть, все в порядке –

 7a68ea36 8288c73d f7c45d8d 22432577 

Я предполагаю, что у меня есть некоторые настройки, но не могу понять, что я пытался сменить между ECB и CBC на стороне java, и это не имело никакого эффекта.

Может кто-нибудь помочь !? пожалуйста….

Поскольку CCCrypt принимает IV, не использует ли он метод шифрования цепочки (например, CBC)? Это будет соответствовать тому, что вы видите: первый блок идентичен, но во втором блоке версия Java применяет оригинальный ключ для шифрования, но версия OSX, похоже, использует что-то еще.

РЕДАКТИРОВАТЬ:

Отсюда я увидел пример. Похоже, вам нужно передать kCCOptionECBMode в CCCrypt:

 ccStatus = CCCrypt(encryptOrDecrypt, kCCAlgorithm3DES, kCCOptionECBMode, <-- this could help vkey, //"123456789012345678901234", //key kCCKeySize3DES, nil, //"init Vec", //iv, vplainText, //"Your Name", //plainText, plainTextBufferSize, (void *)bufferPtr, bufferPtrSize, &movedBytes); 

EDIT 2:

Я играл с некоторой командной строкой, чтобы увидеть, какой из них был прав. Я думал, что смогу внести свой вклад:

 $ echo "Now then and what is this nonsense all about. Do you know?" | openssl enc -aes-128-ecb -K $(echo 1234567890123456 | xxd -p) -iv 0 | xxd 0000000: 7a68 ea36 8288 c73d f7c4 5d8d 2243 2577 zh.6...=..]."C%w 0000010: e66b 32f9 772b 6679 d7c0 cb69 037b 8740 .k2.w+fy...i.{[email protected] 0000020: 883f 8211 7482 29f4 7239 84be b50b 5aea .?..t.).r9....Z. 0000030: eaa7 519b 65e8 fa26 a1bb de52 083b 478f ..Qe.&...R.;G. 

Я потратил несколько недель на дешифрование закодированной в base64 кодированной AES256 строки. Шифрование было выполнено CCCrypt (Objective-C) на iPad. Расшифровка должна была быть выполнена на Java (с использованием Bouncy Castle).

Я, наконец, преуспел и многому научился в этом процессе. Код шифрования был точно таким же, как и выше (я предполагаю, что это взято из примера Objective-C в документации разработчика iPhone).

В документации CCCrypt () не упоминается, что он использует режим CBC по умолчанию (если вы не укажете опцию, например, kCCOptionECBMode). Он упоминает, что IV, если не указано, по умолчанию соответствует всем нулям (так что IV будет байтовым массивом 0x00, 16 членов в длину).

Используя эти две части информации, вы можете создать функционально идентичный модуль шифрования, используя CBC (и избегать использования ECB, который менее безопасен) на Java и OSx / iphone / ipad (CCCrypt).

Функция Cipher init примет третий байтовый массив в качестве третьего аргумента:

 cipher.init(Cipher.ENCRYPT_MODE, keySpec, IV). 

Для тех, кому это нужно, отречение было абсолютно точным … пересмотренный вызов для создания склепа в объективе-c выглядит следующим образом (обратите внимание, что вам нужен режим ECB и заполнение) …

 CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode + kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES128, NULL /* initialization vector (optional) */, [self bytes], dataLength, /* input */ buffer, bufferSize, /* output */ &numBytesEncrypted); 

Просто добавьте к первому сообщению: в вашем объективном коде C / cocoa вы использовали режим CBC, и в вашем java-коде вы использовали EBC, а вектор инициализации IV также не использовался. Шифрование EBC является блочным и CBC-цепочками в предыдущем блоке, поэтому, если ваш текст меньше 1 блока (= 16 байт в вашем примере), текст шифрования, создаваемый обоими, может быть дешифруемым другим (тем же).

Если вы ищете способ стандартизации использования шифров, издание NIST Special Publication 800-38A, 2001 Edition имеет тестовые векторы. Я могу опубликовать код для векторов AES CBC и EBC, если он кому-то поможет.

  • mcrypt устарел, какова альтернатива?
  • Формат открытых ключей RSA
  • Алгоритм MD5 в Objective C
  • Хранение зашифрованных данных в Postgres
  • шифрование / дешифрование в Android с помощью AES
  • Шифрование RSA, получение плохой длины
  • Шифрование и дешифрование строки в C #
  • Java, Как реализовать Shift Cipher (Цезарский шифр)
  • Как использовать OpenSSL для шифрования / дешифрования файлов?
  • Как работают односторонние hash-функции?
  • Как использовать шифрование / дешифрование 3DES в Java?
  • Давайте будем гением компьютера.