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
I am working on my first iPhone application, in that application I have to calculate the length of NSString, I have tried the available methods and solutions here on SO but for the length is always wrong. For example for a string "test4" NSString.length returns 12 while it should return 5.
I have tried NSString's length property and lengthOfBytesUsingEncoding but both return the same result.
Any help would be appreciated.
EDIT
NSString *string = #"test4";
[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; // returns 12
string.length; // returns 12
Complete Code
+(NSString *)AES256Encrypt:(NSString *)data withKey:(NSString *)rawkey{
rawkey = [NSString stringWithFormat:#"%#%#", #"123456789023456", rawkey];
rawkey = [rawkey substringWithRange:NSMakeRange(0, 32)];
NSData *key = [rawkey dataUsingEncoding:NSUTF8StringEncoding];
NSData *iv = [key subdataWithRange:NSMakeRange(0, 16)];
const char *bytes = [data cStringUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%d", data.length); // prints 12
data = [self encode:bytes length:data.length];
NSData *rawData = [data dataUsingEncoding:NSUTF8StringEncoding];
CCCryptorStatus status = kCCSuccess;
NSData *encrypted = [rawData dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:key initializationVector:iv options:kCCOptionPKCS7Padding error:&status];
NSString *text = [encrypted base64EncodedString];
return text;
}
Thanks
NSString *myString = #"test4";
int i =myString.length;
NSLog(#"Count =%d",i);
which print Count = 5
I'm using the NSData+compression.h and the Base64Transcoder.h elements to be able to zip and unzip content.
Basically to unzip the server responses.
The unzip method works perfectly
+ (NSString *) unzip: (NSString*) stringValue{
Byte inputData[[stringValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
[[stringValue dataUsingEncoding:NSUTF8StringEncoding] getBytes:inputData];
size_t inputDataSize = (size_t)[stringValue length];
size_t outputDataSize = EstimateBas64DecodedDataSize(inputDataSize);
Byte outputData[outputDataSize];//prepare a Byte[] for the decoded data
Base64DecodeData(inputData, inputDataSize, outputData, &outputDataSize);
NSData *theData = [[NSData alloc] initWithBytes:outputData length:outputDataSize];
//And now we gunzip:
NSData* result = [theData gzipInflate];//make bigger==gunzip
NSString *temp = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
return temp;
}
But when I try to zip a content, using the simetric way, the gzipDeflate fails, and return an empty or nil value.
This is my zip code
+ (NSData *) zip:(NSData *) theSourceData {
// And now we zip:
NSData *result = [theSourceData gzipDeflate];
Byte inputData[[result length]];
[result getBytes:inputData];
size_t inputDataSize = (size_t)[result length];
size_t outputDataSize = EstimateBas64DecodedDataSize(inputDataSize);
char outputData[outputDataSize];//prepare a Byte[] for the decoded data
Base64EncodeData(inputData, inputDataSize, outputData, &outputDataSize, NO);
NSData *theData = [[NSData alloc] initWithBytes:outputData length:outputDataSize];
return theData;
}
Any suggestions?
Thanks
The problem was on the Base64 encoder.
+ (NSString *) zip:(NSData *) theSourceData {
// And now we zip:
NSData *result = [theSourceData gzipDeflate];
NSString *source = [NSString base64StringFromData:result length:[result length]];
return source;
}
We've integrated the base64StringFromData:length: method to solve it.
Thanks,
Ivan
I'd like to convert a regular NSString into an NSString with the (what I assume are) ASCII hex values and back.
I need to produce the same output that the Java methods below do, but I can't seem to find a way to do it in Objective-C. I've found some examples in C and C++ but I've had a hard time working them into my code.
Here are the Java methods I'm trying to reproduce:
/**
* Encodes the given string by using the hexadecimal representation of its UTF-8 bytes.
*
* #param s The string to encode.
* #return The encoded string.
*/
public static String utf8HexEncode(String s) {
if (s == null) {
return null;
}
byte[] utf8;
try {
utf8 = s.getBytes(ENCODING_UTF8);
} catch (UnsupportedEncodingException x) {
throw new RuntimeException(x);
}
return String.valueOf(Hex.encodeHex(utf8));
}
/**
* Decodes the given string by using the hexadecimal representation of its UTF-8 bytes.
*
* #param s The string to decode.
* #return The decoded string.
* #throws Exception If an error occurs.
*/
public static String utf8HexDecode(String s) throws Exception {
if (s == null) {
return null;
}
return new String(Hex.decodeHex(s.toCharArray()), ENCODING_UTF8);
}
Update: Thanks to drawnonward's answer here's the method I wrote to create the hex NSStrings. It gives me an "Initialization discards qualifiers from pointer target type" warning on the char declaration line, but it works.
- (NSString *)stringToHex:(NSString *)string
{
char *utf8 = [string UTF8String];
NSMutableString *hex = [NSMutableString string];
while ( *utf8 ) [hex appendFormat:#"%02X" , *utf8++ & 0x00FF];
return [NSString stringWithFormat:#"%#", hex];
}
Haven't had time to write the decoding method yet. When I do, I'll edit this to post it for anyone else interested.
Update2: So the method I posted above actually doesn't output what I'm looking for. Instead of outputting hex values in 0-f format, it was instead outputting all numbers. I finally got back to working on this problem and was able to write a category for NSString that exactly duplicates the Java methods I posted. Here it is:
//
// NSString+hex.h
// Created by Ben Baron on 10/20/10.
//
#interface NSString (hex)
+ (NSString *) stringFromHex:(NSString *)str;
+ (NSString *) stringToHex:(NSString *)str;
#end
//
// NSString+hex.m
// Created by Ben Baron on 10/20/10.
//
#import "NSString+hex.h"
#implementation NSString (hex)
+ (NSString *) stringFromHex:(NSString *)str
{
NSMutableData *stringData = [[[NSMutableData alloc] init] autorelease];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [str length] / 2; i++) {
byte_chars[0] = [str characterAtIndex:i*2];
byte_chars[1] = [str characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[stringData appendBytes:&whole_byte length:1];
}
return [[[NSString alloc] initWithData:stringData encoding:NSASCIIStringEncoding] autorelease];
}
+ (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 < len; i++ )
{
[hexString appendString:[NSString stringWithFormat:#"%x", chars[i]]];
}
free(chars);
return [hexString autorelease];
}
#end
The perfect and short way to convert nsstring to hexadecimal values
NSMutableString *tempHex=[[NSMutableString alloc] init];
[tempHex appendString:#"0xD2D2D2"];
unsigned colorInt = 0;
[[NSScanner scannerWithString:tempHex] scanHexInt:&colorInt];
lblAttString.backgroundColor=UIColorFromRGB(colorInt);
The macro used for this code is----
#define UIColorFromRGB(rgbValue)
[UIColor \colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
For these lines of Java
utf8 = s.getBytes(ENCODING_UTF8);
new String(decodedHexString, ENCODING_UTF8);
Objective-C equivalents would be
utf8 = [s UTF8String];
[NSString initWithUTF8String:decodedHexString];
To make an NSString with the hexadecimal representation of a character string:
NSMutableString *hex = [NSMutableString string];
while ( *utf8 ) [hex appendFormat:#"%02X" , *utf8++ & 0x00FF];
You will have to make your own decodeHex function. Just pull two characters out of the string and, if they are valid, add a byte to the result.
There is a problem with your stringToHex method - it drops leading 0s, and ignores 00s. Just as a quick fix, I made the below:
+ (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 < len; i++ )
{
// [hexString [NSString stringWithFormat:#"%02x", chars[i]]]; /*previous input*/
[hexString appendFormat:#"%02x", chars[i]]; /*EDITED PER COMMENT BELOW*/
}
free(chars);
return [hexString autorelease];
}
Thanks to all who contributed on this thread. It was a great help to me. Since things have moved on a little since the original post, here's my updated implementation for iOS 6. I went with the categories approach, but chose to split the load between NSData and NSString. Comments welcomed.
First, the NSString half, which handles decoding a hex encoded string into an NSData object.
#implementation NSString (StringToHexData)
//
// Decodes an NSString containing hex encoded bytes into an NSData object
//
- (NSData *) stringToHexData
{
int len = [self length] / 2; // Target length
unsigned char *buf = malloc(len)
unsigned char *whole_byte = buf;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [self length] / 2; i++) {
byte_chars[0] = [self characterAtIndex:i*2];
byte_chars[1] = [self characterAtIndex:i*2+1];
*whole_byte = strtol(byte_chars, NULL, 16);
whole_byte++;
}
NSData *data = [NSData dataWithBytes:buf length:len];
free( buf );
return data;
}
#end
The changes were mostly for efficiency's sake: some simple old-fashioned pointer arithmetic means I could allocate the whole buffer in one go, and populate it byte by byte. Then the whole thing is passed to NSData in one go.
The encoding part, in NSData, looks like this:
#implementation NSData (DataToHexString)
- (NSString *) dataToHexString
{
NSUInteger len = [self length];
char * chars = (char *)[self bytes];
NSMutableString * hexString = [[NSMutableString alloc] init];
for(NSUInteger i = 0; i < len; i++ )
[hexString appendString:[NSString stringWithFormat:#"%0.2hhx", chars[i]]];
return hexString;
}
#end
Again, some minor changes, though I suspect no efficiency gains here. The use of "%0.2hhx" solved all the problems of missing leading zero's and ensures that only a single-byte is output at a time.
Hope this helps the next person taking this on!
One possible solution:
+(NSString*)hexFromStr:(NSString*)str
{
NSData* nsData = [str dataUsingEncoding:NSUTF8StringEncoding];
const char* data = [nsData bytes];
NSUInteger len = nsData.length;
NSMutableString* hex = [NSMutableString string];
for(int i = 0; i < len; ++i)[hex appendFormat:#"%02X", data[i]];
return hex;
}
So, first off, I would like to thank drawnonward for his answer. This gave me the first function, mean and clean. In the same spirit, I wrote the other one. Hope you like it.
#synthesize unsigned char* value= _value;
- (NSString*) hexString
{
_value[CONSTANT]= '\0';
unsigned char* ptr= _value;
NSMutableString* hex = [[NSMutableString alloc] init];
while ( *ptr ) [hex appendFormat:#"%02x", *ptr++ & 0x00FF];
return [hex autorelease];
}
- (void) setHexString:(NSString*)hexString
{
_value[CONSTANT]= '\0';
unsigned char* ptr= _value;
for (const char* src= [hexString cStringUsingEncoding:NSASCIIStringEncoding];
*src;
src+=2)
{
unsigned int hexByte;
/*int res=*/ sscanf(src,"%02x",&hexByte);
*ptr++= (unsigned char)(hexByte & 0x00FF);
}
*ptr= '\0';
}
My input was an digit base10 string, and the output should be the hex representation in string format. Examples:
#"10" -> #"A"
#"1128" -> #"468"
#"1833828235" -> #"6D4DFF8B"
Implementation:
+ (NSString *) stringToHex:(NSString *)str{
NSInteger result = [str integerValue];
NSString *hexStr = (result)?#"":#"0";
while (result!=0) {
NSInteger reminder = result % 16;
if(reminder>=0 && reminder<=9){
hexStr = [[NSString stringWithFormat:#"%ld",(long)reminder] stringByAppendingString:hexStr];
}else if(reminder==10){
hexStr = [#"A" stringByAppendingString:hexStr];
}else if(reminder==11){
hexStr = [#"B" stringByAppendingString:hexStr];
}else if(reminder==12){
hexStr = [#"C" stringByAppendingString:hexStr];
}else if(reminder==13){
hexStr = [#"D" stringByAppendingString:hexStr];
}else if(reminder==14){
hexStr = [#"E" stringByAppendingString:hexStr];
}else{
hexStr = [#"F" stringByAppendingString:hexStr];
}
result /=16;
}
return hexStr;
}
Perhaps you should use NSString dataUsingEncoding: to encode and initWithData:length:encoding: to decode. Depends on where you are getting the data from.
Ok Here is the problem. I am trying to send through a structure or anything through the apple bluetooth send network packet code. The code to send is below
-(void)sendMessagePacket:(GKSession *)session packetID:(int)packetID withData:(void *)data ofLength:(int)length reliable:(BOOL)howtosend {
static unsigned char networkPacket[maxPacketSize];
const unsigned int packetHeaderSize = 2 * sizeof(int); // we have two "ints" for our header
if(length < (maxPacketSize - packetHeaderSize)) { // our networkPacket buffer size minus the size of the header info
int *pIntData = (int *)&networkPacket[0];
// header info
pIntData[0] = 10;
pIntData[1] = packetID;
// copy data in after the header
memcpy( &networkPacket[packetHeaderSize], data, length );
NSData *packet = [NSData dataWithBytes: networkPacket length: (length+8)];
if(howtosend == YES) {
[session sendDataToAllPeers:packet withDataMode:GKSendDataReliable error:nil];
} else {
[session sendDataToAllPeers:packet withDataMode:GKSendDataUnreliable error:nil];
}
}
}
If anyone could go through this with a comb and explain what is going on that would be greatly appreciated. Next, the receive code.
- (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context {
// Caller whenever data is received from the session
unsigned char *incomingPacket = (unsigned char *)[data bytes];
//EXPECTS THAT WHAT IS IN INCOMING PACKET [0] TO BE OF DATA TYPE INTEGER
int *pIntData = (int *)&incomingPacket[0];
int packetTime = pIntData[0];
int packetID = pIntData[1];
static int lastPacketTime = -1;
switch (packetID) {
case NETWORK_COINTOSS:
//DO SOMETHING
break;
case NETWORK_TEXT_EVENT:
NSString *fewMore = (NSString *)&incomingPacket[8];
fewThings *bitMore = &fewMore[peer];
//NSLog(#"Trace Bit More: %#",fewMore);
break;
default:
break;
}
NSInteger lengthBytes = [data length];
NSLog(#"Length of data : %i", lengthBytes);
}
What i am struggling to understnad being a newcome to objective c is how all this works, how do i access the string that i have send as all efforts to log it cause the program to crash.
Below is the code used to start the send:
NSString *bigWord = #"BigWordBigWord";
NSInteger len = [bigWord length];
[self sendMessagePacket:gameSession packetID:NETWORK_TEXT_EVENT withData:bigWord ofLength:(len) reliable:YES];
Any help would be so appreciated. Thank You.
You really need to change the NSString object into either a UTF8 representation to send, or to archive it as an NSData object you send with the full length - you can't just cast an NSString as a C string (either for sending or receiving!!!).
You can get a C string version of NSString using:
const char *sendString = [bigWord cStringUsingEncoding:NSUTF8StringEncoding]
And then get it out of your incoming NSData object with
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
This guy is sending and receiving the string over network just fine. But, I'm also still getting error on the receiving end.
http://discussions.apple.com/thread.jspa?messageID=10215848
At last got it. GKTank is transferring the data using struct, so I placed my string inside the struct and rest is the history.
typedef struct {
NSString *strInfo;
} myInfo;