MD5 from NSData is always diffrent - ios

I create an MD5 of a file that is deployed with my bundle to decide if I need to import it.
My problem is that when I create the MD5 is always different. Even when I call the MD5 method 10 times in a loop with the same data, I got different results.
Here is my MD% method:
- (NSString*)hashForData:(NSData*)data
{
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5((__bridge const void*)(data), (CC_LONG)data.length, md5Buffer);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", md5Buffer[i]];
return output;
}
- (NSData*)data
{
if (!_data) {
_data = [NSData dataWithContentsOfFile:_path];
}
return _data;
}
Any idea what could be wrong?

Shouldn't that be:
CC_MD5((__bridge const void*)([data bytes]), (CC_LONG)[data length], md5Buffer);
// ^^^^^^^^^^^^ ^^^^^^^^^^^^^
(i.e. you are calculating the MD5 hash of the NSData object (and adjacent memory) instead of the data within the NSData object).

Related

Binary hash representation to HEX/Ascii in Objective-c

I would to log a binary hash representation in the console, using an hex or ascii representation. The algorithm is MD5, so the function is CC_MD5
I get the binary hash representation via a Theos tweak, which is working well.
EDIT: this tweak intercept the CC_MD5 call. The call is implemented in the method described below. When CC_MD5 is called, replaced_CC_MD5 intercept the call.
The app tested, is a simple app which i made myself and it's using this method to calculate MD5 Hash:
- (NSString *) md5:(NSString *) input
{
const char *cStr = [input UTF8String];
unsigned char digest[16];
CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return output;
}
The hashing it's ok, and the app returns to me the correct hash for the input
input = prova
MD5 Digest = 189bbbb00c5f1fb7fba9ad9285f193d1
The function in my Theos Tweak where i manipulate the CC_MD5 function is
EDIT: where data would be cStr, len would be strlen(cStr) and md would be digest.
static unsigned char * replaced_CC_MD5(const void *data, CC_LONG len, unsigned char *md) {
CC_LONG dataLength = (size_t) len;
NSLog(#"==== START CC_MD5 HOOK ====");
// hex of digest
NSData *dataDigest = [NSData dataWithBytes:(const void *)md length:(NSUInteger)CC_MD5_DIGEST_LENGTH];
NSLog(#"%#", dataDigest);
// hex of string
NSData *dataString = [NSData dataWithBytes:(const void *)data length:(NSUInteger)dataLength];
NSLog(#"%#", dataString);
NSLog(#"==== END CC_MD5 HOOK ====");
return original_CC_MD5(data, len, md);
}
The log of dataString it's ok: 70726f76 61 which is the HEX representation of prova
The log of dataDigest is e9aa0800 01000000 b8c00800 01000000 which is, if i understood, the binary hash representation.
How can i convert this representation to have the MD5 Hash digest?
In replaced_CC_MD5 you are displaying md before the call to original_CC_MD5 which sets its value. What you are seeing is therefore random data (or whatever was last stored in md).
Move the call to original_CC_MD5 to before the display statement and you should see the value you expect. (You'll of course need to save the result of the call in a local so you can return the value in the return statement.)

byteArray to Hex NSString - adds some wrong hex content

I am trying to convert the byteArray to a Hex NSString.
Here is the solution that I referred to convert it into hex NSString. But, I discovered It add's ffffffffffffff. How can I get correct hex NSString?
Best way to serialize an NSData into a hexadeximal string
const char myByteArray[] = {
0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,
0x12,0x23,0x34,0x45,
0x56,0x67,0x78,0x89 };
NSData *myByteData=[NSData dataWithBytes:myByteArray length:sizeof(myByteArray)];
NSMutableString *myHexString= [NSMutableString stringWithCapacity:myByteData.length*2];
for(int i=0;i<myByteData.length;i++){
;
NSString *resultString =[NSString stringWithFormat:#"%02lx",(unsigned long)myByteArray[i]];
[myHexString appendString:resultString];
}
The output String
12233445566778ffffffffffffff8912233445566778ffffffffffffff89
Don't use unsigned long for each of your bytes. And what's the point of myByteData if you don't use it?
And since you are not really using char, use uint8_t.
Try this:
const uint8_t myByteArray[] = {
0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,
0x12,0x23,0x34,0x45,
0x56,0x67,0x78,0x89 };
size_t len = sizeof(myByteArray) / sizeof(uint8_t);
NSMutableString *myHexString = [NSMutableString stringWithCapacity:len * 2];
for (size_t i = 0; i < len; i++) {
[myHexString appendFormat:#"%02x", (int)myByteArray[i]];
}
Your initial byte data is char rather than unsigned char. This means that any values >127 (0x7f) will be seen as a twos-complement negative number, giving ffffffffffffff89.
If you change your data to be unsigned char you will get the desired result.
const unsigned char myByteArray[] = {
0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,
0x12,0x23,0x34,0x45,
0x56,0x67,0x78,0x89 };
NSData *myByteData=[NSData dataWithBytes:myByteArray length:sizeof(myByteArray)];
NSMutableString *myHexString= [NSMutableString stringWithCapacity:myByteData.length*2];
for(int i=0;i<myByteData.length;i++){
NSString *resultString =[NSString stringWithFormat:#"%02lx",(unsigned long)myByteArray[i]];
[myHexString appendString:resultString];
}

Xcode NSdata Garbage

I am Working on a Network application ... but before sending it over the network i am testing my packing and unpacking of data ... but i am getting a lot of garbage values
myfield in a ui text field .. my label is a uilabel ... mybutton method is called when a button is pressed
in the rec method the value(garbage) in x varies from -231231223432.... to +3423423423.....
also if i could like to pack a nsstring with this data how will i pack and unpack it
enum
{
gkMessageSent,
gkMessageNotsent
};
-(void)rec:(NSData *)data
{
const char *incomingPacket = (const char *)[data bytes];
char messageType = incomingPacket[0];
switch (messageType)
{
case gkMessageSent:
{
float x = *(float *)(incomingPacket + 1 );
// value of x are not correct here
NSString *resultString = [[NSString alloc] initWithFormat:#"%f",x];
mylabel.text= resultString;
break;
}
case gkMessageNotsent:
{
mylabel.text=#"2";
break;
}
default:
mylabel.text=#"3";
break;
}
}
-(IBAction)mybutton{
float myvalue=[myfield.text floatValue];
// i check myvalue here and its fine
NSMutableData *data= [NSMutableData dataWithCapacity:1+sizeof(float)];
int myrand=1+rand()%3;
if(myrand==1)
{
char messageType = gkMessageSent;
[data appendBytes:&messageType length:1];
[data appendBytes:&myvalue length:sizeof(float)];
}
else {
char messageType = gkMessageNotsent;
[data appendBytes:&messageType length:1];
[data appendBytes:&myvalue length:sizeof(float) ];
}
[self rec:data];
}
After Some Research I found a way to pack an NSString into NSmutabledata but cant figure out the unpacking
-(IBAction)mybutton {
float myvalue=300;
NSString *resultString = [[NSString alloc] initWithFormat:#"%.2f",myvalue];
NSMutableData *data=nil;
data= [NSMutableData dataWithCapacity:1+([resultString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) ];
int myrand=1+rand()%3;
if(myrand==1)
{
char messageType = gkMessageSent;
[data appendBytes:&messageType length:1];
[data appendBytes:[resultString UTF8String] length:[resultString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
}
else {
char messageType = gkMessageNotsent;
[data appendBytes:&messageType length:1];
[data appendBytes:[resultString UTF8String] length:[resultString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
}
[self rec:data];
}
-(void)rec:(NSData *)data{
const char *incomingPacket = (const char *)[data bytes];
char messageType = incomingPacket[0];
switch (messageType)
{
case gkMessageSent:
{
// Have to get the String here
break;
}
case gkMessageNotsent:
{
mylabel.text=#"2";
break;
}
default:
mylabel.text=#"3";
break;
}
}
You should never send "raw" data of unknown size over the network. If you were using integers, you could send the data by not sending it raw, but "correcting" its byte order to "network order" then reversing the process on the other side:
uint32t foo = htonl(myLong);
and to reverse that:
uint32t myLong = ntohl(networkData4bytesLong);
Floats and doubles can be coerced into using the above, but (to my knowledge) there is no standard way to do this. For even the following hack to work, float must be 32bit IEEE format types on both sides (probably true now on most systems).
One way is to create a union with a long and a float in it:
struct foo {
uint32_t lng;
float flt;
};
You should probably add an assert(sizeof(foo) == 4); on both sides too, just to be sure.
You put the float into a union of this type, then use htonl(foo.lng); to convert, and reverse that on the other side.
Perhaps a more reliable (but more difficult way) is to turn the float into a string, send it, then convert back to a floating point type. That said, the above should work for you with the listed assumptions (IEEE, 32bit type);
EDIT: So if you want to use a string, you can do it by appending a null terminated string to the data you send, use a "pascal" type string where the first byte is the length and a NOT null terminated string follows, or you can allow a fixed amount of space that will at least have one terminating NULL. For brevity, I am going to use the 3rd way but the "pascal" way is probably the best to use when you code it.
So, to be 100% sure we have enought space, we'll allocate 20 bytes for the float (way too much):
char floatStr[20];
sprintf(floatStr, "%f", myFloat);
[myData appendBytes:floatStr length:20];
On the other side:
unsigned char *ptr = ...; // set to the start of the string
sscanf(ptr, "%f", &myFloat);
ptr += 20;

How to store CFBitVector (or any CFType) in Core Data using CFData/NSData?

I have limited experience working with the Core Foundation types & collections, so apologies if this is obvious.
I'm using the CFBitVector type to store some bit sequences, and I need to store it in a binary data format (so that it can be added to a Core Data store). The most sensible thing seems to be to store this in a CFData type, which can be toll-free bridged with an NSData and added to the store, but I am unsure of how to do this.
Can anybody help me out with a simple example of storing CFTypes in CF/NSData?
Edit:
Is this even the right approach? Should I try converting the CFBitVector into a series of ints which can then be stored in the data model? Or perhaps a transformable attribute?
The way I ended up doing this was to roll my own attribute transformer in order to convert a CFBitVectorRef into an NSData instance. The benefit of this is that I can really cram the bit array tightly into a block of binary data, as in my case I really need to keep the storage size to a minimum.
Below is the implementation of my CFBitVectorTransformer class. It essentially reads each bit and packs them into unsigned chars ("segments" in the code below), which are then appended to a mutable NSData buffer. The code would work with types larger than unsigned chars, however I wanted the smallest chunks possible in order to really minimise the size of the resulting data.
#define kBitsPerByte 8
#implementation CFBitVectorTransformer
+ (Class)transformedValueClass
{
return [NSData class];
}
+ (BOOL)allowsReverseTransformation
{
return YES;
}
/* CFBitVectorRef -> NSData */
- (id)transformedValue:(id)value
{
if (!value) return nil;
if ([value isKindOfClass:[NSData class]]) return value;
/* Prepare the bit vector. */
CFBitVectorRef bitVector = (__bridge CFBitVectorRef)value;
CFIndex bitVectorCount = CFBitVectorGetCount(bitVector);
/* Prepare the data buffer. */
NSMutableData *bitData = [NSMutableData data];
unsigned char bitVectorSegment = 0;
NSUInteger bytesPerSegment = sizeof(char);
NSUInteger bitsPerSegment = bytesPerSegment * kBitsPerByte;
for (CFIndex bitIndex = 0; bitIndex < bitVectorCount; bitIndex++) {
/* Shift the bit into the segment the appropriate number of places. */
CFBit bit = CFBitVectorGetBitAtIndex(bitVector, bitIndex);
int segmentShift = bitIndex % bitsPerSegment;
bitVectorSegment |= bit << segmentShift;
/* If this is the last bit we can squeeze into the segment, or it's the final bit, append the segment to the data buffer. */
if (segmentShift == bitsPerSegment - 1 || bitIndex == bitVectorCount - 1) {
[bitData appendBytes:&bitVectorSegment length:bytesPerSegment];
bitVectorSegment = 0;
}
}
return [NSData dataWithData:bitData];
}
/* NSData -> CFBitVectorRef */
- (id)reverseTransformedValue:(id)value
{
if (!value) return NULL;
if (![value isKindOfClass:[NSData class]]) return NULL;
/* Prepare the data buffer. */
NSData *bitData = (NSData *)value;
char *bitVectorSegments = (char *)[bitData bytes];
NSUInteger bitDataLength = [bitData length];
/* Prepare the bit vector. */
CFIndex bitVectorCapacity = bitDataLength * kBitsPerByte;
CFMutableBitVectorRef bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, bitVectorCapacity);
CFBitVectorSetCount(bitVector, bitVectorCapacity);
for (NSUInteger byteIndex = 0; byteIndex < bitDataLength; byteIndex++) {
unsigned char bitVectorSegment = bitVectorSegments[byteIndex];
/* Store each bit of this byte in the bit vector. */
for (NSUInteger bitIndex = 0; bitIndex < kBitsPerByte; bitIndex++) {
CFBit bit = bitVectorSegment & 1 << bitIndex;
CFIndex bitVectorBitIndex = (byteIndex * kBitsPerByte) + bitIndex;
CFBitVectorSetBitAtIndex(bitVector, bitVectorBitIndex, bit);
}
}
return (__bridge_transfer id)bitVector;
}
#end
This nicely abstracts the conversion of data, allowing you to just set the CFBitVectorRef as an attribute in the data model, and should be plenty fast enough for most purposes.
I hope this helps somebody else in a similar situation.

Find Character String In Binary Data

I have a binary file I've loaded using an NSData object. Is there a way to locate a sequence of characters, 'abcd' for example, within that binary data and return the offset without converting the entire file to a string? Seems like it should be a simple answer, but I'm not sure how to do it. Any ideas?
I'm doing this on iOS 3 so I don't have -rangeOfData:options:range: available.
I'm going to award this one to Sixteen Otto for suggesting strstr. I went and found the source code for the C function strstr and rewrote it to work on a fixed length Byte array--which incidentally is different from a char array as it is not null terminated. Here is the code I ended up with:
- (Byte*)offsetOfBytes:(Byte*)bytes inBuffer:(const Byte*)buffer ofLength:(int)len;
{
Byte *cp = bytes;
Byte *s1, *s2;
if ( !*buffer )
return bytes;
int i = 0;
for (i=0; i < len; ++i)
{
s1 = cp;
s2 = (Byte*)buffer;
while ( *s1 && *s2 && !(*s1-*s2) )
s1++, s2++;
if (!*s2)
return cp;
cp++;
}
return NULL;
}
This returns a pointer to the first occurrence of bytes, the thing I'm looking for, in buffer, the byte array that should contain bytes.
I call it like this:
// data is the NSData object
const Byte *bytes = [data bytes];
Byte* index = [self offsetOfBytes:tag inBuffer:bytes ofLength:[data length]];
Convert your substring to an NSData object, and search for those bytes in the larger NSData using rangeOfData:options:range:. Make sure that the string encodings match!
On iPhone, where that isn't available, you may have to do this yourself. The C function strstr() will give you a pointer to the first occurrence of a pattern within the buffer (as long as neither contain nulls!), but not the index. Here's a function that should do the job (but no promises, since I haven't tried actually running it...):
- (NSUInteger)indexOfData:(NSData*)needle inData:(NSData*)haystack
{
const void* needleBytes = [needle bytes];
const void* haystackBytes = [haystack bytes];
// walk the length of the buffer, looking for a byte that matches the start
// of the pattern; we can skip (|needle|-1) bytes at the end, since we can't
// have a match that's shorter than needle itself
for (NSUInteger i=0; i < [haystack length]-[needle length]+1; i++)
{
// walk needle's bytes while they still match the bytes of haystack
// starting at i; if we walk off the end of needle, we found a match
NSUInteger j=0;
while (j < [needle length] && needleBytes[j] == haystackBytes[i+j])
{
j++;
}
if (j == [needle length])
{
return i;
}
}
return NSNotFound;
}
This runs in something like O(nm), where n is the buffer length, and m is the size of the substring. It's written to work with NSData for two reasons: 1) that's what you seem to have in hand, and 2) those objects already encapsulate both the actual bytes, and the length of the buffer.
If you're using Snow Leopard, a convenient way is the new -rangeOfData:options:range: method in NSData that returns the range of the first occurrence of a piece of data. Otherwise, you can access the NSData's contents yourself using its -bytes method to perform your own search.
I had the same problem.
I solved it doing the other way round, compared to the suggestions.
first, I reformat the data (assume your NSData is stored in var rawFile) with:
NSString *ascii = [[NSString alloc] initWithData:rawFile encoding:NSAsciiStringEncoding];
Now, you can easily do string searches like 'abcd' or whatever you want using the NSScanner class and passing the ascii string to the scanner. Maybe this is not really efficient, but it works until the -rangeOfData method will be available for iPhone also.

Resources