Retrieve NSData to Hex by length - iphone

I got a NSData that contain bytes like <00350029 0033> with length 6, is there any correct way to split the bytes to array somehow like (00, 35, 00, 29, 00, 33) ?

NSData *data = ...;
NSMutableArray *bytes = [NSMutableArray array];
for (NSUInteger i = 0; i < [data length]; i++) {
unsigned char byte;
[data getBytes:&byte range:NSMakeRange(i, 1)];
[bytes addObject:[NSString stringWithFormat:#"%x", byte]];
}
NSLog(#"%#", bytes);
(Assuming you want the bytes as a hex string representation, as in your example. Otherwise, use NSNumber.)

You could use the NSData method
- (void)getBytes:(void *)buffer range:(NSRange)range
to get the bytes in a given range (after having allocated the right amount of memory, using malloc), then use
+ (id)dataWithBytes:(const void *)bytes length:(NSUInteger)length
to create new small (1 byte long) data objects which you then put into an array. However if you just retrieve the pointer to the bytes themselves (using [data bytes]), that gives you a pointer (kind of an array in the C sense, not an NSArray, but could also be used and far more efficient).

static NSString* HexStringFromNSData(NSData* data) {
NSUInteger n = data.length;
NSMutableString* s = [NSMutableString stringWithCapacity:(2 * n)];
const unsigned char* ptr = [data bytes];
for(NSUInteger i = 0; i < n; i++, ptr++) {
[s appendFormat:#"%02x", (long)*ptr];
}
return [NSString stringWithString:s];
}

Related

blowfish algorithm objective c

I have to use Blowfish algorithm in my code for encryption and decryption. After calling the decryption method, blowfishDecrypt, I am getting the value in NSData but it give me always null when I convert it to NSString.
I am using the following code :
-(void)methodCalled
{
syncTime=#"c7c937169084b20c3ff882dcda193a59";
NSData* data = [syncTime dataUsingEncoding:NSUTF8StringEncoding];
NSData* data2 = [#"R=U!LH$O2B#" dataUsingEncoding:NSUTF8StringEncoding];
NSData* dycryptData=[self blowfishDecrypt:data usingKey:data2];
// prints <0eec37b6 2b76c2df cdf72356 0f033ed8 d6bd37dd 5223bf66 5c318ebe 07f3cf71>
NSLog(#"%#",dycryptData);
NSString *dSync=[[NSString alloc] initWithBytes:[dycryptData bytes]
length:[dycryptData length]
encoding:NSUTF8StringEncoding];
// prints (null)
NSLog(#"Sync timeis %#",dSync);
}
-(NSData *)blowfishDecrypt:(NSData *)messageData
usingKey:(NSData *)secretKeyData {
NSMutableData *decryptedData = [messageData mutableCopy];
BLOWFISH_CTX ctx;
Blowfish_Init (&ctx, (unsigned char*)[secretKeyData bytes], [secretKeyData length]);
NSRange aLeftRange, aRightRange;
NSData *aLeftBox, *aRightBox;
unsigned long dl = 0, dr = 0;
for (int i = 0; i< [decryptedData length]; i += 8) { // Divide data into octets...
// …and then into quartets
aLeftRange = NSMakeRange(i, 4);
aRightRange = NSMakeRange(i + 4, 4);
aLeftBox = [decryptedData subdataWithRange:aLeftRange];
aRightBox = [decryptedData subdataWithRange:aRightRange];
// Convert bytes into unsigned long
[aLeftBox getBytes:&dl length:sizeof(unsigned long)];
[aRightBox getBytes:&dr length:sizeof(unsigned long)];
// Decipher
Blowfish_Decrypt(&ctx, &dl, &dr);
// Put bytes back
[decryptedData replaceBytesInRange:aLeftRange withBytes:&dl];
[decryptedData replaceBytesInRange:aRightRange withBytes:&dr];
}
return decryptedData;
}
Blowfish library code can be found eg. here
HINT#1 //general answer
NSString provides an initializer for this purpose. You can see more info using the docs here.
NSString * dSync = [[NSString alloc] initWithData: dycryptData
encoding:NSUTF8StringEncoding];
Assuming you use ARC.
HINT#2 // the answer for this particular question
I tried your code and confirm the above NSString conversion returns null. So why it is not working? dycryptData is stream of bytes represented as hex, so I tried the following and received the desired result:
int dycryptData_len = [dycryptData length];
NSMutableString *dSync_hex = [NSMutableString stringWithCapacity:dycryptData_len*2];
const unsigned char *dycryptData_bytes = [dycryptData bytes];
for (int i = 0; i < dycryptData_len; ++i) {
[dSync_hex appendFormat:#"%02x", dycryptData_bytes[i]];
}
NSLog(#"dSync_hex=%#",dSync_hex);
I can see this result in log output:
dSync_hex=0eec37b62b76c2dfcdf723560f033ed8d6bd37dd5223bf665c318ebe07f3cf71

How to convert NSString to hexadecimal string of fixed block size

In my application I am converting a NSString to HexString. But I always require a fixed size(16 bytes) hex string e.g. if the length of my hex string is 15 bytes, I want it to be 16 bytes. I know that I can add zeros at the beginning of the hex string, but how to add that because simply adding a "0" is not working while I am converting it back into NSString.
You can try this code....
+ (NSString *) stringToHex:(NSString *)str
{
NSUInteger len = [str length];
unichar *chars = malloc(len * sizeof(unichar));
[str getCharacters:chars];
NSMutableString *hexString = [[NSMutableString alloc] init];
for(NSUInteger i = 0; i &lt len; i++ )
{
// [hexString [NSString stringWithFormat:#"%02x", chars[i]]]; //previous input
[hexString appendFormat:#"%02x", chars[i]]; //EDITED PER COMMENT BELOW
}
free(chars);
return [hexString autorelease];
}
I hope this will help you.
happy coding.

How to read bytes from NSData

Can anyone suggest a method to read bytes from NSData (like read function in #interface NSInputStream : NSStream)
How to read binary bytes in NSData? may help you:
NSString *path = #"…put the path to your file here…";
NSData * fileData = [NSData dataWithContentsOfFile: path];
const char* fileBytes = (const char*)[fileData bytes];
NSUInteger length = [fileData length];
NSUInteger index;
for (index = 0; index<length; index++) {
char aByte = fileBytes[index];
//Do something with each byte
}
You can also create an NSInputStream from an NSData object, if you need the read interface:
NSData *data = ...;
NSInputStream *readData = [[NSInputStream alloc] initWithData:data];
[readData open];
However, you should be aware that initWithData copies the contents of data.
One of the simplest ways is to use NSData getBytes:range:.
NSData *data = ...;
char buffer[numberOfBytes];
[data getBytes:buffer range:NSMakeRange(position, numberOfBytes)];
where position and length is the position you want to read from in NSData and the length is how many bytes you want to read. No need to copy.
Alex already mentioned NSData getBytes:range: but there is also NSData getBytes:length: which starts from the first byte.
NSData *data = ...;
char buffer[numberOfBytes];
[data getBytes:buffer length:numberOfBytes];
May way of doing that..
do not forget to free byte array after usage.
NSData* dat = //your code
NSLog(#"Receive from Peripheral: %#",dat);
NSUInteger len = [dat length];
Byte *bytedata = (Byte*)malloc(len);
[dat getBytes:bytedata length:len];
int p = 0;
while(p < len)
{
printf("%02x",bytedata[p]);
if(p!=len-1)
{
printf("-");
}//printf("%c",bytedata[p]);
p++;
}
printf("\n");
// byte array manipulation
free(bytedata);

How to create byte array from NSData

Please any one guide me how to create bytes array from nsdata here is my code for createing nsdata
NSData* data = UIImagePNGRepresentation(img);
If you only want to read them, there's a really easy method :
unsigned char *bytes = [data bytes];
If you want to edit the data, there's a method on NSData that does this.
// Make your array to hold the bytes
NSUInteger length = [data length];
unsigned char *bytes = malloc( length * sizeof(unsigned char) );
// Get the data
[data getBytes:bytes length:length];
NB Don't forget - if you're copying the data, you also have to call free(bytes) at some point ;)
Here is fastest way (but pretty danger) to get array:
unsigned char *bytesArray = data.bytes;
NSUInteger lengthOfBytesArray = data.length;
before trying to get byte#100 you should check lengthOfBytesArray like:
if (lengthOfBytesArray > 100 + 1)
{
unsigned char byteWithOffset100 = bytesArray[100];
}
And another safe and more objc-like way:
- (NSArray*) arrayOfBytesFromData:(NSData*) data
{
if (data.length > 0)
{
NSMutableArray *array = [NSMutableArray arrayWithCapacity:data.length];
NSUInteger i = 0;
for (i = 0; i < data.length; i++)
{
unsigned char byteFromArray = data.bytes[i];
[array addObject:[NSValue valueWithBytes:&byteFromArray
objCType:#encode(unsigned char)]];
}
return [NSArray arrayWithArray:array];
}
return nil;
}

Convert hex data string to NSData in Objective C (cocoa)

fairly new iPhone developer here. Building an app to send RS232 commands to a device expecting them over a TCP/IP socket connection. I've got the comms part down, and can send ASCII commands fine. It's the hex code commands I'm having trouble with.
So lets say I have the following hex data to send (in this format):
\x1C\x02d\x00\x00\x00\xFF\x7F
How do I convert this into an NSData object, which my send method expects?
Obviously this does not work for this hex data (but does for standard ascii commands):
NSString *commandascii;
NSData *commandToSend;
commandascii = #"\x1C\x02d\x00\x00\x00\xFF\x7F";
commandToSend = [commandascii dataUsingEncoding:NSStringEncoding];
For a start, some of the \x hex codes are escape characters, and I get an "input conversion stopped..." warning when compiling in XCode. And NSStringEncoding obviously isn't right for this hex string either.
So the first problem is how to store this hex string I guess, then how to convert to NSData.
Any ideas?
Code for hex in NSStrings like "00 05 22 1C EA 01 00 FF". 'command' is the hex NSString.
command = [command stringByReplacingOccurrencesOfString:#" " withString:#""];
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
for (int i = 0; i < ([command length] / 2); i++) {
byte_chars[0] = [command characterAtIndex:i*2];
byte_chars[1] = [command characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[commandToSend appendBytes:&whole_byte length:1];
}
NSLog(#"%#", commandToSend);
Here's an example decoder implemented on a category on NSString.
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
unsigned char strToChar (char a, char b)
{
char encoder[3] = {'\0','\0','\0'};
encoder[0] = a;
encoder[1] = b;
return (char) strtol(encoder,NULL,16);
}
#interface NSString (NSStringExtensions)
- (NSData *) decodeFromHexidecimal;
#end
#implementation NSString (NSStringExtensions)
- (NSData *) decodeFromHexidecimal;
{
const char * bytes = [self cStringUsingEncoding: NSUTF8StringEncoding];
NSUInteger length = strlen(bytes);
unsigned char * r = (unsigned char *) malloc(length / 2 + 1);
unsigned char * index = r;
while ((*bytes) && (*(bytes +1))) {
*index = strToChar(*bytes, *(bytes +1));
index++;
bytes+=2;
}
*index = '\0';
NSData * result = [NSData dataWithBytes: r length: length / 2];
free(r);
return result;
}
#end
If you can hard code the hex data:
const char bytes[] = "\x00\x12\x45\xAB";
size_t length = (sizeof bytes) - 1; //string literals have implicit trailing '\0'
NSData *data = [NSData dataWithBytes:bytes length:length];
If your code must interpret the hex string (assuming the hex string is in a variable called inputData and lengthOfInputData is the length of inputData):
#define HexCharToNybble(x) ((char)((x > '9') ? tolower(x) - 'a' + 10 : x - '0') & 0xF)
int i;
NSMutableData *data = [NSMutableData data];
for (i = 0; i < lengthOfInputData;)
{
char byteToAppend;
if (i < (lengthOfInputData - 3) &&
inputData[i+0] == '\\' &&
inputData[i+1] == 'x' &&
isxdigit(inputData[i+2]) &&
isxdigit(inputData[i+3]))
{
byteToAppend = HexCharToNybble(inputData[i+2]) << 4 + HexCharToNybble(input[i+3]);
i += 4;
}
else
{
byteToAppend = inputData[i];
i += 1;
}
[data appendBytes:&byteToAppend length:1];
}
This is an old topic, but I'd like to add some remarks.
• Scanning a string with [NSString characterAtIndex] is not very efficient.
Get the C string in UTF8, then scan it using a *char++ is much faster.
• It's better to allocate NSMutableData with capacity, to avoid time consuming block resizing. I think NSData is even better ( see next point )
• Instead of create NSData using malloc, then [NSData dataWithBytes] and finally free, use malloc, and [NSData dataWithBytesNoCopy:length:freeWhenDone:]
It also avoids memory operation ( reallocate, copy, free ). The freeWhenDone boolean tells the NSData to take ownership of the memory block, and free it when it will be released.
• Here is the function I have to convert hex strings to bytes blocks. There is not much error checking on input string, but the allocation is tested.
The formatting of the input string ( like remove 0x, spaces and punctuation marks ) is better out of the conversion function.
Why would we lose some time doing extra processing if we are sure the input is OK.
+(NSData*)bytesStringToData:(NSString*)bytesString
{
if (!bytesString || !bytesString.length) return NULL;
// Get the c string
const char *scanner=[bytesString cStringUsingEncoding:NSUTF8StringEncoding];
char twoChars[3]={0,0,0};
long bytesBlockSize = formattedBytesString.length/2;
long counter = bytesBlockSize;
Byte *bytesBlock = malloc(bytesBlockSize);
if (!bytesBlock) return NULL;
Byte *writer = bytesBlock;
while (counter--) {
twoChars[0]=*scanner++;
twoChars[1]=*scanner++;
*writer++ = strtol(twoChars, NULL, 16);
}
return[NSData dataWithBytesNoCopy:bytesBlock length:bytesBlockSize freeWhenDone:YES];
}
If I want to hard-code the bytes, I do something like this:
enum { numCommandBytes = 8 };
static const unsigned char commandBytes[numCommandBytes] = { 0x1c, 0x02, 'd', 0x0, 0x0, 0x0, 0xff, 0x7f };
If you're obtaining these backslash-escaped bytes at run time, try the strunvis function.
Obviously this does not work for this hex data (but does for standard ascii commands):
NSString *commandascii;
NSData *commandToSend;
commandascii = #"\x1C\x02d\x00\x00\x00\xFF\x7F";
commandToSend = [commandascii dataUsingEncoding:NSStringEncoding];
For a start, some of the \x hex codes are escape characters, and I get an "input conversion stopped..." warning when compiling in XCode. And NSStringEncoding obviously isn't right for this hex string either.
First, it's Xcode, with a lowercase c.
Second, NSStringEncoding is a type, not an encoding identifier. That code shouldn't compile at all.
More to the point, backslash-escaping is not an encoding; in fact, it's largely independent of encoding. The backslash and 'x' are characters, not bytes, which means that they must be encoded to (and decoded from) bytes, which is the job of an encoding.
Another way to do it.
-(NSData *) dataFromHexString:(NSString *) hexstr
{
NSMutableData *data = [[NSMutableData alloc] init];
NSString *inputStr = [hexstr uppercaseString];
NSString *hexChars = #"0123456789ABCDEF";
Byte b1,b2;
b1 = 255;
b2 = 255;
for (int i=0; i<hexstr.length; i++) {
NSString *subStr = [inputStr substringWithRange:NSMakeRange(i, 1)];
NSRange loc = [hexChars rangeOfString:subStr];
if (loc.location == NSNotFound) continue;
if (255 == b1) {
b1 = (Byte)loc.location;
}else {
b2 = (Byte)loc.location;
//Appending the Byte to NSData
Byte *bytes = malloc(sizeof(Byte) *1);
bytes[0] = ((b1<<4) & 0xf0) | (b2 & 0x0f);
[data appendBytes:bytes length:1];
b1 = b2 = 255;
}
}
return data;
}
-(NSData*) convertToByteArray:(NSString*) command {
if (command == nil || command.length == 0) return nil;
NSString *command1 = command;
if(command1.length%2 != 0) {
// to handle odd bytes like 1000 decimal = 3E8 with is of length = 3
command1 = [NSString stringWithFormat:#"0%#",command1];
}
NSUInteger length = command1.length/2 ;
NSMutableData *commandToSend = [[NSMutableData alloc] initWithLength:length];
char byte_chars[3] = {'\0','\0','\0'};
unsigned char whole_byte;
for (int i=0; i<length; i++) {
byte_chars[0] = [command1 characterAtIndex:i*2];
byte_chars[1] = [command1 characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[commandToSend appendBytes:&whole_byte length:1];
}
NSRange commandRange = NSMakeRange(commandToSend.length - length, length);
NSData *result = [commandToSend subdataWithRange:commandRange];
return result;
}
I know this is a very old thread, but there is an encoding scheme in Objective C that can easily convert your string of hex codes into ASCII characters.
1) remove the \x from the string and with out keeping spaces in the string just convert the string to NSData using :
[[NSData alloc] initWithData:[stringToBeConverted dataUsingEncoding:NSASCIIStringEncoding]];
Hex data is just bytes in memory, you think of it as a string because that's how you see it but they could represent anything.
Try: (typed in the browser, may contain errors)
NSMutableData *hexData = [[NSMutableData alloc] init];
[hexData appendBytes: 0x1C];
[hexData appendBytes: 0x02D];
etc...