Я пытаюсь зашифровать некоторые данные из python (Google App Engine), а затем расшифровать их на iOS.
Есть несколько проблем, связанных с этим, из-за того, что с AES Encryption существует очень много вариантови различные форматы, доступные в Python и Objective-C.
Из-за ограниченной доступности библиотек PyCrypto в Google App Engine и кода AES на стороне iOS / Objective-C, требующего PKCS7Padding, я решил использовать slowAES на стороне Python.
Я также использую 16-битный ключ, режим CBC и PKCS7Padding.
Учитывая, что это моя функция шифрования и вспомогательные переменные / функция:
def str2nums(s):
return map(ord, s)
key = "hjt4mndfy234n5fs"
moo = aes.AESModeOfOperation()
iv = [12, 34, 96, 15] * 4
CBC_mode = moo.modeOfOperation['CBC']
nkey = str2nums(key)
def encrypt(plaintext):
funcName = inspect.stack()[0][3]
logging.debug("Enter " + funcName)
logging.debug("Input string: " + plaintext)
m, s, encData = moo.encrypt(plaintext, CBC_mode, nkey, len(nkey), iv)
fmt = len(encData)*'B'
dataAsStr = ""
for j in encData:
dataAsStr = dataAsStr + str(j) + ","
logging.debug("Output encrypted data:[" + dataAsStr + "]")
encoded = base64.b64encode(struct.pack(fmt, *encData))
logging.debug("Output encrypted string: " + encoded)
decoded = struct.unpack(fmt, base64.b64decode(encoded))
decrypted = moo.decrypt(decoded, s, CBC_mode, nkey, len(nkey), iv)
logging.debug("Output decrypted back: " + decrypted)
return encoded
Обратите внимание, что на стороне Python я шифрую, упаковываю, а затем кодирую данные base64.Перед возвратом этих зашифрованных данных я также делаю тестовый прогон при его расшифровке, чтобы показать, что в журналах он действительно работает.
На iOS я использую следующее дополнение AES NSData:
- (NSData *)AES128DecryptWithKey:(NSString *)key {
// 'key' should be 16 bytes for AES128, 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:NSASCIIStringEncoding];
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 numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer); //free the buffer;
return nil;
}
И я использую это, когда я опускаю base64 / упакованные / зашифрованные данные примерно так:
NSMutableString * result = [[NSMutableString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
if (LOG) { NSLog(@"Base64 encoded / Encrypted string: %@", result); }
NSData* encryptedData = [NSData decodeBase64ForString:result]; // base64 decode
if (LOG) { NSLog(@"Encrypted string: %@", encryptedData); }
NSData* decryptedData = [encryptedData AES128DecryptWithKey:@"hjt4mndfy234n5fs"]; // AES Decrypt
Проблема в том, что я не могу показатьсячтобы правильно расшифровать данные на стороне клиента (iOS), даже если они прекрасно дешифруются на сервере (в python).
Во время дешифрования cryptStatus всегда заканчивается: kCCAlignmentError. Что я не совсем понимаю.
Я также перепутал с AES 256, но мне нужен32-битный ключ, я думаю, и это не вариант для slowAES в режиме CBC (по крайней мере, в соответствии с примерами?).
Ведение журнала сервера (Обратите внимание, что фактические незашифрованные данные являются просто пустым набором []. Это представление в JSON-формате для возврата клиенту.
2012-01-04 08:48:13.962
Enter encrypt
D 2012-01-04 08:48:13.962
Input string: []
D 2012-01-04 08:48:13.967
Output encrypted data:[4,254,226,26,101,240,22,113,44,54,209,203,233,64,208,255,]
D 2012-01-04 08:48:13.967
Output encrypted string: BP7iGmXwFnEsNtHL6UDQ/w==
D 2012-01-04 08:48:13.971
Output decrypted back: []
Ведение журнала клиента (iOS):
2012-01-04 12:45:13.891 Base64 encoded / Encrypted string: BP7iGmXwFnEsNtHL6UDQ/w==
2012-01-04 12:45:13.892 Encrypted string: <04fee21a 65f01671 2c36d1cb e940d0ff>
2012-01-04 12:45:29.126 Decrypted string:
Итак, мои вопросы:
- Что означает «ошибка выравнивания»? Или что я делаю неправильно, что не хочетрасшифровывать на клиенте?
- Нужно ли вообще беспокоиться о распаковке данных, учитывая, что они выглядят так, как будто они хорошо сочетаются? И если да, то как мне поступить с функцией unpack () в C или Objective?-C?
- Есть ли просто лучший способ сделать шифрование AES между Google App Engine и iOS?
РЕДАКТИРОВАТЬ: я должен также отметить, что помимо ответа использовать тот жеВектор инициализации, я обнаружил несоответствие между кодом Python и iOS для заполнения. Шифрование / дешифрование отлично работало для небольших объемов данных, но затем я не смог расшифровать с большими. Я исправил это, изменив iOSсторона, чтобы НЕ использовать PKCS7Padding и поставить вместо этого 0.