Populate NSData directly from NSString that contains "HEX" representation [duplicate] - objective-c

I'm trying to convert a Hex NSString to NSData (I'm using the below attached code). The following is the output:
<00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000>
which looks totally irrelevant to me. Any idea/ suggestions on where its going wrong?
NSString *strData = #"72ff63cea198b3edba8f7e0c23acc345050187a0cde5a9872cbab091ab73e553";
NSLog(#"string Data length is %d",[strData length]);
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[2];
int i;
for (i=0; i < [strData length]/2; i++) {
byte_chars[0] = [strData characterAtIndex:i*2];
byte_chars[1] = [strData characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, [strData length]);
[commandToSend appendBytes:&whole_byte length:1];
}
NSLog(#"%#", commandToSend);

NSString *command = #"72ff63cea198b3edba8f7e0c23acc345050187a0cde5a9872cbab091ab73e553";
command = [command stringByReplacingOccurrencesOfString:#" " withString:#""];
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (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 is another method that also handles leading <, trailing > and embedded spaces such as
<9dc69faf a7434ba9 aef57f5c 365d571f 4c3753c4 ae13db42 57d184ca e00246c5>
Code:
+ (NSData *)dataFromHexString:(NSString *)string
{
string = [string lowercaseString];
NSMutableData *data= [NSMutableData new];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i = 0;
int length = string.length;
while (i < length-1) {
char c = [string characterAtIndex:i++];
if (c < '0' || (c > '9' && c < 'a') || c > 'f')
continue;
byte_chars[0] = c;
byte_chars[1] = [string characterAtIndex:i++];
whole_byte = strtol(byte_chars, NULL, 16);
[data appendBytes:&whole_byte length:1];
}
return data;
}
This is based on the answer by #Nikunj R. Jadav

This might be more useful, Apple has shared a NSData category.
NSData+HexString.m
The code is:
#implementation NSData (HexString)
// Not efficent
+(id)dataWithHexString:(NSString *)hex
{
char buf[3];
buf[2] = '\0';
NSAssert(0 == [hex length] % 2, #"Hex strings should have an even number of digits (%#)", hex);
unsigned char *bytes = malloc([hex length]/2);
unsigned char *bp = bytes;
for (CFIndex i = 0; i < [hex length]; i += 2) {
buf[0] = [hex characterAtIndex:i];
buf[1] = [hex characterAtIndex:i+1];
char *b2 = NULL;
*bp++ = strtol(buf, &b2, 16);
NSAssert(b2 == buf + 2, #"String should be all hex digits: %# (bad digit around %d)", hex, i);
}
return [NSData dataWithBytesNoCopy:bytes length:[hex length]/2 freeWhenDone:YES];
}
#end

I see several solution have been post only able to convert string with even length.
So here is my solution which also able return correct data if the string is odd length like this "DBA" became data like this this "\x0D\xBA"
+ (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:1];
}
return data;
}

Related

CBCMac (DESede) implementation in objective c

Has any one implemented CBC Mac (DESede) in Objective c? Could you show sample code or explain how to correct my code?
Here is my effort so far....
-(void)tryMac
{
unsigned char blockCount;
unsigned char key[16] = "\x1\x2\x3\x4\x5\x6\x7\x8\x9\x0\x1\x2\x3\x4\x5\x6";
unsigned char data[16] = "\x54\x68\x69\x73\x69\x73\x6d\x79\x73\x74\x72\x69\x6e\x67\x0\x0";
DES_cblock *desKey1 = (DES_cblock* ) key;
DES_cblock *desKey2 = (DES_cblock* ) key;
unsigned char *iv = (unsigned char *) malloc(8);
memset(iv, 0x0, 8);
DES_set_odd_parity(desKey1);
DES_set_odd_parity(desKey2);
DES_key_schedule schedule1;
DES_key_schedule schedule2;
DES_set_key_checked(desKey1, &schedule1);
DES_set_key_checked(desKey2, &schedule2);
int len = sizeof(data);
blockCount = len / 4;
int lastBlock = 0;
for(unsigned char i = 0; i < blockCount; i++)
{
int bufferLen = sizeof(data)/blockCount;
unsigned char buffer[bufferLen];
memccpy(buffer, data, lastBlock, bufferLen);
lastBlock = (i + 1) * bufferLen;
unsigned char *result = (unsigned char *) malloc(4);
if (lastBlock == len)
{
DES_ede2_cbc_encrypt(buffer, result, bufferLen, &schedule1, &schedule2, (DES_cblock *) iv, DES_ENCRYPT);
NSData *encryptedData = [NSData dataWithBytes:(const void *)result length:4];
NSString *encryptedString = [self stringWithHexFromData:encryptedData];
NSLog(#"Encrypted Block %#",encryptedString);
}
}

How do I convert a raw-byte-string to NSData? [duplicate]

I'm trying to convert a Hex NSString to NSData (I'm using the below attached code). The following is the output:
<00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000>
which looks totally irrelevant to me. Any idea/ suggestions on where its going wrong?
NSString *strData = #"72ff63cea198b3edba8f7e0c23acc345050187a0cde5a9872cbab091ab73e553";
NSLog(#"string Data length is %d",[strData length]);
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[2];
int i;
for (i=0; i < [strData length]/2; i++) {
byte_chars[0] = [strData characterAtIndex:i*2];
byte_chars[1] = [strData characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, [strData length]);
[commandToSend appendBytes:&whole_byte length:1];
}
NSLog(#"%#", commandToSend);
NSString *command = #"72ff63cea198b3edba8f7e0c23acc345050187a0cde5a9872cbab091ab73e553";
command = [command stringByReplacingOccurrencesOfString:#" " withString:#""];
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (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 is another method that also handles leading <, trailing > and embedded spaces such as
<9dc69faf a7434ba9 aef57f5c 365d571f 4c3753c4 ae13db42 57d184ca e00246c5>
Code:
+ (NSData *)dataFromHexString:(NSString *)string
{
string = [string lowercaseString];
NSMutableData *data= [NSMutableData new];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i = 0;
int length = string.length;
while (i < length-1) {
char c = [string characterAtIndex:i++];
if (c < '0' || (c > '9' && c < 'a') || c > 'f')
continue;
byte_chars[0] = c;
byte_chars[1] = [string characterAtIndex:i++];
whole_byte = strtol(byte_chars, NULL, 16);
[data appendBytes:&whole_byte length:1];
}
return data;
}
This is based on the answer by #Nikunj R. Jadav
This might be more useful, Apple has shared a NSData category.
NSData+HexString.m
The code is:
#implementation NSData (HexString)
// Not efficent
+(id)dataWithHexString:(NSString *)hex
{
char buf[3];
buf[2] = '\0';
NSAssert(0 == [hex length] % 2, #"Hex strings should have an even number of digits (%#)", hex);
unsigned char *bytes = malloc([hex length]/2);
unsigned char *bp = bytes;
for (CFIndex i = 0; i < [hex length]; i += 2) {
buf[0] = [hex characterAtIndex:i];
buf[1] = [hex characterAtIndex:i+1];
char *b2 = NULL;
*bp++ = strtol(buf, &b2, 16);
NSAssert(b2 == buf + 2, #"String should be all hex digits: %# (bad digit around %d)", hex, i);
}
return [NSData dataWithBytesNoCopy:bytes length:[hex length]/2 freeWhenDone:YES];
}
#end
I see several solution have been post only able to convert string with even length.
So here is my solution which also able return correct data if the string is odd length like this "DBA" became data like this this "\x0D\xBA"
+ (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:1];
}
return data;
}

NSString to UTF8String error when contains chinese character

I tried to encrypt a data that might contains chinese character, however i kept getting null when I decrypt the string. the way I encrypt the data is derived from our android team, So I wanna keep it the same. It looks like when I call [[NSString alloc] initWithData:dataFrom64 encoding:NSUTF8StringEncoding]; It gives me a NSString representation of an UTF8String. and when I call NSString UTF8String, it returns something unexpected. I tried to print out every thing to see where goes wrong. Sorry for the mess.
I really need help on this. I can't figure out how to solve it.
NSLog(#"--------Test begins--------");
NSString *chinese = #"abcd 測試";
/** encrypt **/
char const *testCStr = [testString UTF8String];
char const *cStr = [chinese UTF8String];
char *newCStr = (char*)calloc(sizeof(char), strlen(cStr));
strcpy(newCStr, cStr);
int lenStr = strlen(cStr);
int lenKey = testString.length;
for (int i = 0, j = 0; i < lenStr; i++, j++) {
if (j >= lenKey) j = 0;
newCStr[i] = cStr[i] ^ testCStr[j];
}
NSString *tempStr = [NSString stringWithUTF8String:[[NSString stringWithFormat:#"%s",newCStr] UTF8String]];
NSData *tempData = [tempStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64Str = [tempData base64EncodedString];
char const *dataCStr = [tempData bytes];
NSString* dataToStr = [[NSString alloc] initWithData:tempData
encoding:NSUTF8StringEncoding];
NSLog(#"chinese : %#", chinese);
NSLog(#"chinese utf8 : %s ", [chinese UTF8String]);
NSLog(#"encrypted utf8 : %s ", newCStr);
NSLog(#"--------Encrypt--------");
NSLog(#"encrypted str : %#", tempStr);
NSLog(#"temp data bytes : %s", dataCStr);
NSLog(#"data to str : %#", dataToStr);
NSLog(#"base64 data : %#", base64Str);
NSLog(#"data temp : %#", tempData );
/** decrypt**/
NSData *dataFrom64 = [NSData dataFromBase64String:base64Str];
NSString *strFromData = [[NSString alloc] initWithData:dataFrom64
encoding:NSUTF8StringEncoding];
char const *cStrFromData = [strFromData UTF8String];
char *newStr2 = (char*)calloc(sizeof(char), strlen(cStrFromData));
strcpy(newStr2, cStrFromData);
for (int i = 0, j = 0; i < lenStr; i++, j++) {
if (j >= lenKey) j = 0;
newStr2[i] = cStrFromData[i] ^ testCStr[j];
}
NSLog(#"--------Decrypt--------");
NSLog(#"data 64 : %#", dataFrom64 );
NSLog(#"data 64 bytes : %s", [dataFrom64 bytes]);
NSLog(#"str from data : %#", strFromData);
NSLog(#"cStr from data : %s", [strFromData UTF8String]);
NSLog(#"decrypt utf8 : %s", newStr2);
NSLog(#"decrypt str : %#", [NSString stringWithUTF8String:newStr2]);
and here is the out put:
--------Test begins--------
chinese : abcd 測試
chinese utf8 : abcd 測試
encrypted utf8 : #!B5aºÄõ–ôá
--------Encrypt--------
encrypted str : #!B5aºÄõ–ôá
temp data bytes : #!B5aºÄõ–ôá6.889 WebSocke
data to str : #!B5aºÄõ–ôá
base64 data : IyFCNWHCusOEw7XigJPDtMOh
data temp : <23214235 61c2bac3 84c3b5e2 8093c3b4 c3a1>
--------Decrypt--------
data 64 : <23214235 61c2bac3 84c3b5e2 8093c3b4 c3a1>
data 64 bytes : #!B5aºÄõ–ôá
str from data : #!B5aºÄõ–ôá
cStr from data : #!B5aºÄõ–ôá
decrypt utf8 : abcd òÇÙºÛî‚Äì√¥√°
decrypt str : (null)
--------test ends--------
The problem is that newCStr is not null-terminated, and does also not represent a valid
UTF-8 string. So this conversion
NSString *tempStr = [NSString stringWithUTF8String:[[NSString stringWithFormat:#"%s",newCStr] UTF8String]];
is bound to fail (or give a wrong result).
The following code avoids unnecessary conversions:
NSLog(#"--------Test begins--------");
NSString *plainText = #"abcd 測試";
NSString *keyString = #"topsecret";
/** encrypt **/
NSMutableData *plainData = [[plainText dataUsingEncoding:NSUTF8StringEncoding] mutableCopy];
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
uint8_t *plainBytes = [plainData mutableBytes];
const uint8_t *keyBytes = [keyData bytes];
for (int i = 0, j = 0; i < [plainData length]; i++, j++) {
if (j >= [keyData length]) j = 0;
plainBytes[i] ^= keyBytes[j];
}
NSString *base64Str = [plainData base64EncodedString];
NSLog(#"chinese : %#", plainText);
NSLog(#"--------Encrypt--------");
NSLog(#"base64 data : %#", base64Str);
/** decrypt**/
NSData *dataFrom64 = [NSData dataFromBase64String:base64Str];
NSMutableData *decodeData = [dataFrom64 mutableCopy];
uint8_t *decodeBytes = [decodeData mutableBytes];
for (int i = 0, j = 0; i < [decodeData length]; i++, j++) {
if (j >= [keyData length]) j = 0;
decodeBytes[i] ^= keyBytes[j];
}
NSString *decrypted = [[NSString alloc] initWithData:decodeData
encoding:NSUTF8StringEncoding];
NSLog(#"--------Decrypt--------");
NSLog(#"decrypt str : %#", decrypted);
Output:
--------Test begins--------
chinese : abcd 測試
--------Encrypt--------
base64 data : FQ0TF0WFysmc3ck=
--------Decrypt--------
decrypt str : abcd 測試

Objective-C RC4 Decryption

I am new to Objective-C, but am an experienced developer (C#), but I can't figure this out:
I have a string which is RC4 encrypted, and I need to decrypt it using Objective-C on the iPad (iOS 5.0). I have looked all over the net for a working example, but have had no luck finding an example that works end-to-end. Not only does the code below not return the decrypted string correctly, it returns something different every time it executes, which makes me thing a pointer is being released someplace.
Note: I do not know if it matters, but the string was encrypted using http://archive.plugins.jquery.com/project/RC4 and then stored as text in a Sqlite database, which I am now accessing from Objective-C (I know, the architecture sounds messy, but I can't change that at this point.)
The code I am using is (taken from RC4 encryption - CommonCrypto (Objective-C) vs PHP):
+ (NSString*)decryptData:(NSData*) dataToDecrypt
{
const void *vplainText;
size_t plainTextBufferSize;
plainTextBufferSize = [dataToDecrypt length];
vplainText = [dataToDecrypt bytes];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
NSString *key = #"theKeyIUsedtoEncryptInTheFirstPlace";
const void *vkey = (const void *) [key UTF8String];
size_t keyLength = [[key dataUsingEncoding:NSUTF8StringEncoding] length];
ccStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmRC4,
0,
vkey,
kCCKeySizeDES,
nil,
vplainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes);
if (ccStatus == kCCSuccess) NSLog(#"SUCCESS");
/*else*/ if (ccStatus == kCCParamError) return #"PARAM ERROR";
else if (ccStatus == kCCBufferTooSmall) return #"BUFFER TOO SMALL";
else if (ccStatus == kCCMemoryFailure) return #"MEMORY FAILURE";
else if (ccStatus == kCCAlignmentError) return #"ALIGNMENT";
else if (ccStatus == kCCDecodeError) return #"DECODE ERROR";
else if (ccStatus == kCCUnimplemented) return #"UNIMPLEMENTED";
NSString *result = [[ NSString alloc ] initWithData: [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSASCIIStringEncoding];
NSLog(#"%#", result);
return result;
}
Use this function for encryption and decryption. (Just put in the encoded string with same key again to decode it).
-(NSString*) rc4Key:(NSString*) key str:(NSString*) str
{
int j = 0;
unichar res[str.length];
const unichar* buffer = res;
unsigned char s[256];
for (int i = 0; i < 256; i++)
{
s[i] = i;
}
for (int i = 0; i < 256; i++)
{
j = (j + s[i] + [key characterAtIndex:(i % key.length)]) % 256;
swap(s[i], s[j]);
}
int i = j = 0;
for (int y = 0; y < str.length; y++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
swap(s[i], s[j]);
unsigned char f = [str characterAtIndex:y] ^ s[ (s[i] + s[j]) % 256];
res[y] = f;
}
return [NSString stringWithCharacters:buffer length:str.length];
}
I see a couple of references to DES in your code (kCCKeySizeDES, kCCBlockSize3DES). That doesn't seem right -- at a minimum, kCCKeySizeDES should probably be replaced with keyLength.
If that doesn't solve it, I'd look next at possible text encoding issues. The data in SQLite might be UTF8-encoded binary data, in which case you'll probably have to "decode" it by converting from UTF8 to ISO8859-1.
RC4 implementation translated from .net:
+(NSString*)RC4:(NSString *)data key:(NSString *)key
{
id x;
int y = 0;
int i = 0;
int j = 0;
NSMutableArray *box = [[NSMutableArray alloc] initWithCapacity:256];
NSString *result = #"";
for (i = 0; i < 256; i++) {
[box addObject:[NSNumber numberWithInt:i]];
}
for (i = 0; i < 256; i++) {
j = ((int)[key characterAtIndex:(i % key.length)] + [[box objectAtIndex:i] intValue] + j) % 256;
x = [box objectAtIndex:i];
[box setObject:[box objectAtIndex:j] atIndexedSubscript:i];
[box setObject:x atIndexedSubscript:j];
}
for (i = 0; i < data.length; i++) {
y = i % 256;
j = ([[box objectAtIndex:y] intValue] + j) % 256;
x = [box objectAtIndex:y];
[box setObject:[box objectAtIndex:j] atIndexedSubscript:y];
[box setObject:x atIndexedSubscript:j];
NSString *c = [NSString stringWithFormat:#"%c", ([data characterAtIndex:i] ^ (char)[[box objectAtIndex:([[box objectAtIndex:y] intValue] + [[box objectAtIndex:j] intValue]) % 256] intValue])];
result = [result stringByAppendingString:c];
}
return result;
}

Insert a #"\n" in NSString

For example, if I start with this string:
NSString * labeltext = #"abcdefghijk";
I want this string change to #"abc\n def\n ghi \n jk".
I want #"\n" to be inserted at an interval of 3.
How can I accomplish this?
Use a NSMutableString and then for loop through the original NSString.
NSMutableString *buffer = [[NSMutableString alloc] init];
int len = [labelText length];
for (i = 0; i < len; i++) {
NSRange charAt = NSMakeRange(i,1);
[buffer appendString: [labelText substringWithRange: charAt]];
if ((i % 3) == 2) {
[buffer appendString: #"\n"];
}
}
labelText = (NSString *)buffer;
The above example is pure Objective-C. This can also be accomplished using C. Convert the NSString into a cstring and then loop through the array. For instance,
const char *str = [labelText UTF8String];
int len = strlen(str) - 1;
int pos = 0;
char buffer[(len * 2) + 1];
for (i = 0; i < len; i++) {
char ch = str[i];
buffer[pos] = ch;
pos++;
if ((i % 3) == 2) {
buffer[pos] = '\n';
pos++;
}
}
buffer[pos] = '\0';
labelText = [NSString stringWithFormat: #"%s", buffer];