2014-09-29 3 views
2

Я получаю часть зашифрованного json от вызова веб-службы отдыха. Следующий код Ruby правильно декодирует ответ обратно на json. Полученные данные сначала декодируются base64, тогда первые 16 байтов рассматриваются как iv, а остальные - как данные. Сначала ключ де-шестнадцатеричный (отсутствие лучшего выражения).Objective c декодирование зашифрованных данных

encrypted = Base64.decode64(res) #base 64 decode 

de_cipher = OpenSSL::Cipher::Cipher.new("AES-128-CBC") 
de_cipher.decrypt 
de_cipher.key = [key].pack('H*') #de-hex the key 
de_cipher.iv = encrypted[0..15] # the first 16 bytes is the IV 

descrypted = de_cipher.update(encrypted) << de_cipher.final; 
json_string = descrypted[16 .. (descrypted.size - 1)] #taking away the first 16, rest is data 

Код рубина был просто подготовкой для меня, чтобы понять данные. Мне действительно нужно называть этот веб-сервис и декодировать в объективе c на iPhone. Но пока не повезло, и я не могу расшифровать полученную строку до правильного json. Ниже то, что у меня есть:

//self.responseData is received through NSURLConnection, pretty sure it is piece together correctly. But there is \r\n at the end, which made it not correct length for base64, so I took the last two bytes away. 
NSString *str = [[[NSString alloc] initWithData:[self.responseData subdataWithRange:(NSRange){0, self.responseData.length - 2}] encoding:NSUTF8StringEncoding] autorelease]; 
NSLog(@"tvm get token response = [%@]",str); 

//CreateDataWithHexString is something I found on stack overflow, supposed to reverse hex string to binary 
NSString * key =[[MyProfile sharedInstance] getOneProperty:TVM_KEY]; 
//NSData *keyData = [[NSData alloc] initWithBase64EncodedString:key options:0]; 
NSData *keyData = [self CreateDataWithHexString:key]; 

//base64 decode the received string 
NSData * whole = [[NSData alloc] initWithBase64EncodedString:str options:0]; 
NSData * iv = [whole subdataWithRange:(NSRange){0, 16}]; 
NSData * data = [whole subdataWithRange:(NSRange){16, whole.length - 16}]; 

CCCryptorStatus ccStatus = kCCSuccess; 
size_t   cryptBytes = 0; // Number of bytes moved to buffer. 
NSMutableData *dataOut = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128]; 

ccStatus = CCCrypt(kCCDecrypt, 
        kCCAlgorithmAES128, 
        kCCOptionPKCS7Padding, 
        keyData.bytes, 
        kCCKeySizeAES128, 
        iv.bytes, 
        data.bytes, 
        data.length, 
        dataOut.mutableBytes, 
        dataOut.length, 
        &cryptBytes); 

if (ccStatus == kCCSuccess) { 
    dataOut.length = cryptBytes; 
    NSString * json = [dataOut base64Encoding]; 
    NSLog(@"json = [%@]", dataOut); 
    NSLog(@"json = [%@]", json); 
} 
else { 

Ключ был первоначально генерироваться следующим образом, надеюсь, что это имеет смысл, чтобы де-шестигранник, как описано выше:

CFUUIDRef theKeyUUID = CFUUIDCreate(NULL); 
CFStringRef keyuuid = CFUUIDCreateString(NULL, theKeyUUID); 
CFRelease(theKeyUUID); 
//server side expect a uuid without those -'s. 
NSString * key = [(__bridge NSString *)keyuuid stringByReplacingOccurrencesOfString:@"-" withString:@""]; 
CFRelease(keyuuid); 

Ниже CreateDataWithHexString я нашел на переполнение стека, мы надеемся, это для правильной цели здесь:

-(NSData *)CreateDataWithHexString:(NSString *)inputString 
{ 
NSUInteger inLength = [inputString length]; 

unichar *inCharacters = alloca(sizeof(unichar) * inLength); 
[inputString getCharacters:inCharacters range:NSMakeRange(0, inLength)]; 

UInt8 *outBytes = malloc(sizeof(UInt8) * ((inLength/2) + 1)); 

NSInteger i, o = 0; 
UInt8 outByte = 0; 
for (i = 0; i < inLength; i++) { 
    UInt8 c = inCharacters[i]; 
    SInt8 value = -1; 

    if  (c >= '0' && c <= '9') value =  (c - '0'); 
    else if (c >= 'A' && c <= 'F') value = 10 + (c - 'A'); 
    else if (c >= 'a' && c <= 'f') value = 10 + (c - 'a'); 

    if (value >= 0) { 
     if (i % 2 == 1) { 
      outBytes[o++] = (outByte << 4) | value; 
      outByte = 0; 
     } else { 
      outByte = value; 
     } 

    } else { 
     if (o != 0) break; 
    } 
} 

return [[NSData alloc] initWithBytesNoCopy:outBytes length:o freeWhenDone:YES]; 
} 

ответ

1

В конце концов, часть расшифровки была в порядке, но дисплей был неправильным. Это все из-за этой одной линии:

NSString * json = [dataOut base64Encoding]; 

Я не смотрел на расшифрованных данных, а его Base64 строка в кодировке, очевидно, это не будет выглядеть как действительный JSON.

Смежные вопросы