I have NSMutableData "30352514 38001300 00000001"
i need convert byte to bit
00110000001101
and that to NSString
Thx
Use this for bytes:
const char *byte = [data bytes];
NSLog(#"%s",byte);
This is for bits:
const char *byte = [data bytes];
unsigned int length = [data length];
for (int i=0; i<length; i++) {
char n = byte[i];
char buffer[9];
buffer[8] = 0; //for null
int j = 8;
while(j > 0)
{
if(n & 0x01)
{
buffer[--j] = '1';
} else
{
buffer[--j] = '0';
}
n >>= 1;
}
printf("%s ",buffer);
Related
My server devs ask me to send them some data encoded with base64 with this rules:
big-endian byte order
no extra zero bytes
base64 string
for example:
10005000 → «mKol»
1234567890 → «SZYC0g»
I did some spaghetti code, and it's work. But maybe somebody have more elegant solution?
+ (NSString*)encodeBigEndianBase64:(uint32_t)value {
char *bytes = (char*) &value;
int len = sizeof(uint32_t);
char *reverseBytes = malloc(sizeof(char) * len);
unsigned long index = len - 1;
for (int i = 0; i < len; i++)
reverseBytes[index--] = bytes[i];
int offset = 0;
while (reverseBytes[offset] == 0) {
offset++;
}
NSData *resultData;
if (offset > 0) {
int truncatedLen = (len - offset);
char *truncateBytes = malloc(sizeof(char) * truncatedLen);
for (int i = 0; i < truncatedLen ; i++)
truncateBytes[i] = reverseBytes[i + offset];
resultData = [NSData dataWithBytes:truncateBytes length:truncatedLen];
free(truncateBytes);
} else {
resultData = [NSData dataWithBytes:reverseBytes length:len];
}
free(reverseBytes);
return [[resultData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength] stringByReplacingOccurrencesOfString:#"=" withString:#""];
}
Little bit improved solution (thanks to zaph):
+ (NSString*)encodeBigEndianBase64:(uint32_t)value {
uint32_t swappedValue = CFSwapInt32HostToBig(value);
char *swappedBytes = (char*) &swappedValue;
int len = sizeof(uint32_t);
int offset = 0;
while (swappedBytes[offset] == 0) {
offset++;
}
NSData *resultData;
if (offset > 0) {
int truncatedLen = (len - offset);
char *truncateBytes = malloc(sizeof(char) * truncatedLen);
for (int i = 0; i < truncatedLen ; i++)
truncateBytes[i] = swappedBytes[i + offset];
resultData = [NSData dataWithBytes:truncateBytes length:truncatedLen];
free(truncateBytes);
} else {
resultData = [NSData dataWithBytes:swappedBytes length:len];
}
return [[resultData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength] stringByReplacingOccurrencesOfString:#"=" withString:#""];
}
For endian conversions use htons(), htonl(), ntohs(), ntohl()
network byte order is bigendian
`htons()` // host to network short
`htonl()` // host to network ling
`ntohs()` // network to host long
`ntohl()` // network to host long
These are defined in endan.h
Also see Byte-Order Utilities Reference
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);
}
}
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;
}
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;
}
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;
}