So.. I have encrypted data from server that need to be decrypted so that I can get the full response JSON. The thing is I need to split the first 16 bytes of data to get the IV for decryption and the rest of the bytes is the encrypted data. I tried below method:
NSData *wholeData = [[NSData alloc] initWithBase64EncodedString:#"IYSaYh92saFT5t/ueQQtlTaFT1oW33FXPLDUsRMATBLUrY/6Z1VGK1KFmyeRwHpbi85T7ZNzDQAl5v8cu60DcJLwVQDI6KdwbmCq0+L62IM7Ixw60+G8gTkm+6+MLtyE" options:0];
NSData *d1 = [wholeData subdataWithRange:NSMakeRange(0, 16)];
NSData *d2 = [wholeData subdataWithRange:NSMakeRange(17, wholeData.length)];
NSData *enc = d2;
NSData *key = [[NSData alloc] initWithBase64EncodedString:#"alskd81039aisdf/tusd8341iasldkjfY=" options:0];
NSData *enciv = d1;
NSData *decrypted = [FBEncryptorAES decryptData:enc key:key iv:enciv];
Then I got below error:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSConcreteData subdataWithRange:]: range {17, 96} exceeds data length 96'
How can I fix my issue?
NSData *d2 = [wholeData subdataWithRange:NSMakeRange(17, wholeData.length - 17)];
you can try this
NSData* blob;
NSUInteger length = [blob length];
NSUInteger chunkSize = 100 * 1024;
NSUInteger offset = 0;
do {
NSUInteger thisChunkSize = length - offset > chunkSize ? chunkSize : length - offset;
NSData* chunk = [NSData dataWithBytesNoCopy:(char *)[blob bytes] + offset
length:thisChunkSize
freeWhenDone:NO];
offset += thisChunkSize;
// do something with chunk
} while (offset < length);
Related
We are facing problem while creating compressed file at iOS Device Document Directory, .tgz file is in Hex string transferring from pin-pad device to iPad iOS App at TCP socket layer. We used below HexToString function to convert that hex string and make file with .tgz. but at the end file is corrupted.
Can anyone please help us here, how to create compress file at iOS level with below hex string ? Please suggest us any code changes.
Note :- we had tried multiple NSStringEncoding technique, like ASCII, Unicode, Utf8, etc.
HEX String:-
1F8B08003058A8620203EDCA3B0A80301045D1594A5660265FB7E036065422A8453282CB57B4B2B112419CD3DCE2BD6966DD8F54925E4A975B62D22551EE741A2A5E199E80BBE8F1681DFDA5270BC6DB60D1398735A0092E0650082F580A53566A6F36F7BFFBFDA39A01841042FCD0062C8057FA00080000
we are using Xcode Version:13.1 and IOS Version 15.1 and above.
//Below function we used for creating .tgz file
//fileName here is abc.tgz which is compress file type
//content here is hex string mention aboved
+ (void)writeToLogFile:(NSString*)content fileName:(NSString*)fileNameString{
content = [NSString stringWithFormat:#"%#",content];
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:fileNameString];
NSData *fileOriginalString = [self HextoString:content];
NSData *fileData = [fileOriginalString dataUsingEncoding:NSASCIIStringEncoding];
***//In alternative we also tried direct hex string to NSData type by calling below commentented method but it still failing
//NSData *fileData = [self dataFromHexString:content];***
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSError *error = nil;
[fileData writeToFile:fileName options:NSDataWritingAtomic error:&error];
NSLog(#"Write returned error: %#", [error localizedDescription]);
});
}
//Below function we used for Hex to String conversion
+(NSString*)HextoString:(NSString*)string{
#try{
NSMutableString * StrResult = [[NSMutableString alloc] init];
int i = 0;
while (i < [string length]){
NSString * hexChar = [string substringWithRange: NSMakeRange(i, 2)];
int value = 0;
sscanf([hexChar cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value);
[StrResult appendFormat:#"%c", (char)value];
i+=2;
}
return StrResult;
}
#catch (NSException *exception){
[AELoggerManager info:[NSString stringWithFormat:#" %s EXCEPTION ::%#",__FUNCTION__,exception]];
}
}
+ (NSData *)dataFromHexString:(NSString *) string {
if([string length] % 2 == 1){
string = [#"0"stringByAppendingString:string];
}
const char *chars = [string UTF8String];
int i = 0, len = (int)[string length];
NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:2];
}
return data;
}
The first method is:
-(NSData *)stringToAddBytes:(NSString*)addString
{
int length = (int)[addString length];
if(length < 2)
{
return nil;
}
Byte buf[length / 2];
for(int i = 0 ;i < length/2 ;i++)
{
NSString *str = [addString substringWithRange:NSMakeRange(i * 2, 2)];
Byte b = [self hexStringToByte:str];
buf[i]=b;
}
NSData * myD = [[NSData alloc]initWithBytes:buf length:length/2];
return myD;
}
THe method that the first method called.
-(Byte)hexStringToByte:(NSString*)str
{
NSArray *charArray = [[NSArray alloc]initWithObjects:#"0",#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",
#"A",#"B",#"C",#"D",#"E",#"F",nil];
NSString *str1 = [str substringWithRange:NSMakeRange(0, 1)];
int num1 = (int)[charArray indexOfObject:str1];
NSString *str2 = [str substringWithRange:NSMakeRange(1, 1)];
int num2 = (int)[charArray indexOfObject:str2];
Byte b = num1*16+num2;
return b;
}
Thank you for your answer.It looks change large char to small char.
hexStringToByte: wil convert string with hexadecimal number representation (example #"FF") to Byte value (in this example 255).
stringToAddBytes: uses hexStringToByte: to create NSData of bytes breaking addString into two letter peases and converting them to Byte values.
In other words, this is string serialization.
Example:
// 255 = 0xFF
// 170 = 0xAA
// 136 = 0x88
NSString* addString = #"FFAA88";
NSData* data = [self stringToAddBytes:addString];
// data will be [255, 170, 136]
Be aware that NSData is not an array, instead, it represents a raw object.
I'm trying to split up NSData into smaller <100 length chunks so I can send them over CoreBluetooth but for some reason, it decides to mess up occasionally, proven by the fact that trying to combine the data and decoding the object from within the same method fails. Because of this, I'm assuming I'm splitting up the NSData wrong?
Here is the code I'm using to split it up (Taken from some kind stranger on stackoverflow!)
// Split up the data and put into Array
NSUInteger length = [data length];
NSUInteger chunkSize = 100;
NSUInteger offset = 0;
do {
NSUInteger thisChunkSize = length - offset > chunkSize ? chunkSize : length - offset;
NSData* chunk = [NSData dataWithBytesNoCopy:(char *)[data bytes] + offset
length:thisChunkSize freeWhenDone:NO];
offset += thisChunkSize;
[orderQueue addObject:chunk];
} while (offset < length);
The data is then recombined and the object unarchived as so:
NSMutableData *finishedData = [[NSMutableData alloc] init];
for (NSData *dataChunk in orderQueue) {
[finishedData appendData:dataChunk];
}
Order *order = [NSKeyedUnarchiver unarchiveObjectWithData:finishedData]; // ERRORS OUT ON THIS LINE
finishedData = [[NSMutableData alloc] init];
dataChunks = [[NSMutableArray alloc] init];
On paper, I honestly think I'm doing it right but it still bugs out occasionally. Any ideas why this might be? :< I get the following error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive (0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30)'
I just ran this code to check your logic and it's correct.
NSMutableArray *orderQueue = [[NSMutableArray alloc] init];
NSString *originalString = #"Here are some strings for you.";
for (NSInteger i = 0; i < 1000; ++i)
{
#autoreleasepool {
originalString = [originalString stringByAppendingString:#"\nHere are some strings for you."];
}
}
NSData *data = [originalString dataUsingEncoding:NSUTF8StringEncoding];
// Split up the data and put into Array
NSUInteger length = [data length];
NSUInteger chunkSize = 100;
NSUInteger offset = 0;
do {
NSUInteger thisChunkSize = length - offset > chunkSize ? chunkSize : length - offset;
NSData* chunk = [NSData dataWithBytesNoCopy:(char *)[data bytes] + offset
length:thisChunkSize freeWhenDone:NO];
offset += thisChunkSize;
[orderQueue addObject:chunk];
} while (offset < length);
NSMutableData *finishedData = [[NSMutableData alloc] init];
for (NSData *dataChunk in orderQueue) {
[finishedData appendData:dataChunk];
}
NSString *recreatedString = [[NSString alloc] initWithData:finishedData encoding:NSUTF8StringEncoding];
NSLog(#"%#", recreatedString);
NSLog(#"%#", [originalString isEqualToString:recreatedString] ? #"Equal" : #"Error");
Your error must be somewhere else, potentially in the way you're responding to the <NSCoding> protocol in the Order class.
I have an NSData object that contains just <64> which is supposed to represent the int 100
How can I convert this NSData to an int?
I can convert it to it's Chr equivalent d using
NSString *string = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
but I need the Dec equivalent of 100
Thanks
<64> means that the NSData object contains a single byte with the value 0x64 = 100,
so the following should work;
const uint8_t *bytes = [data bytes]; // pointer to the bytes in data
int value = bytes[0]; // first byte
int *b = (int *)data.bytes;
printf("%d",*b); //prints 100
Below logic converts NSData to integer perefctly. Length of bytes does not matter. It just works.
NSData *data;
NSString *stringData = [data description];
stringData = [stringData substringWithRange:NSMakeRange(1, [stringData length]-2)];
unsigned dataAsInt = 0;
NSScanner *scanner = [NSScanner scannerWithString: stringData];
[scanner scanHexInt:& dataAsInt];
I need to represent a NSInteger and NSString into array of bytes. below are the sample of what I am looking for.
For how, this harcodings are working fine. I want to do this through code. Any clue.
First, NSInteger into bytes of Hex:
NSInteger test = 1;
unsigned char byte[] = { 0x00, 0x01 };
NSInteger test = 16;
unsigned char byte[] = { 0x00, 0x10 };
NSData *data = [NSData dataWithBytes:byte length:sizeof(byte)];
Second, NSString into bytes of Hex:
NSString *test = #"31C5B562-BD07-4616-BCBD-130BA6822790";
unsigned char byte[] = {0x31, 0xC5, 0xB5, 0x62, 0xBD, 0x07, 0x46, 0x16, 0xBC, 0xBD, 0x13, 0x0B, 0xA6, 0x82, 0x27, 0x90};
NSData *data = [NSData dataWithBytes:byte length:sizeof(byte)];
I tried with below code and it works well for my UUID but for NSInteger to to be working I need to send "0010" instead of 16 and "0001" instead of 1. So any clue on how to do this conversion.
- (NSData *)hexData {
NSMutableData *hexData = [NSMutableData data];
int idx = 0;
for (idx = 0; idx+2 <= self.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [self substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[hexData appendBytes:&intValue length:1];
}
return hexData;
}
EDIT:
int8_t test = -59;
int8_t bytes = CFSwapInt16HostToBig(test);
NSData *data1 = [NSData dataWithBytes:&bytes length:sizeof(bytes)];
Reaching as 0xFF instead of 0xC4
Since your string is a UUID string you can do something like this:
NSString *test = #"";
uuid_t uuid;
uuid_parse([test UTF8String], uuid)
NSData *data = [NSData dataWithBytes:uuid length:16];
For the number you can do:
NSInteger test = 1;
NSData *data = [NSData dataWithBytes:&test length:sizeof(test)];
Keep in mind that NSInteger is probably more than two bytes and you may also need to worry about byte order.
Update: Since it seems you need the integer value to be two bytes, you should do:
uint16_t test = 1;
NSData *data = [NSData dataWithBytes:&test length:sizeof(test)];
This will ensure 2 bytes. You also need to worry about byte ordering so you really need:
uint16_t test = 1;
uint16_t bytes = CFSwapInt16HostToBig(test);
NSData *data = [NSData dataWithBytes:&bytes length:sizeof(bytes)];
Change CFSwapInt16HostToBig to CFSwapInt16HostToLitte if appropriate.