Я шифрую строку в цели-c и также шифрую ту же строку в использовании Java AES и вижу некоторые странные проблемы. Первая часть результата совпадает до определенного момента, но затем это отличается, следовательно когда я иду для декодирования результата Java на iPhone это, наклон дешифрует его.
Я использую исходную строку "Теперь затем и о чем является эта ерунда всеми. Вы знаете?" Используя ключ "1234567890123456"
Объективный-c код для шифрования следующий:Примечание: это - категория NSData, так предположите, что метод называют на объекте NSData, таким образом, 'сам' содержит данные байта для шифрования.
- (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
Я предполагаю, что имею некоторые отличающиеся настройки, но не могу разработать то, что, я пытался изменить между ЕЦБ и 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);
РЕДАКТИРОВАТЬ 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.{.@
0000020: 883f 8211 7482 29f4 7239 84be b50b 5aea .?..t.).r9....Z.
0000030: eaa7 519b 65e8 fa26 a1bb de52 083b 478f ..Q.e..&...R.;G.
Для всех, кому это нужно, отречение было абсолютно правильным ... пересмотренный призыв к созданию склепа в объекте-c выглядит следующим образом (обратите внимание на нужен режим ECB И дополнение) ...
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode + kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
Я потратил несколько недель на расшифровку строки в кодировке 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 примет массив байтов IV в качестве третьего аргумента:
cipher.init(Cipher.ENCRYPT_MODE, keySpec, IV).