I am trying to encrypt/decrypt one field of SQLite3 database stored in iPhone app.
I am using this category mentioned in this question.
While encrypting, I am using following code:
NSString *key = #"pass123";
NSString *secret = webNote.note;
NSData *plain = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *cipher = [plain AES256EncryptWithKey:key];
sqlite3_bind_text(statement, 1, [[cipher description] UTF8String], -1, SQLITE_TRANSIENT);
It does save data into the field in 74657874 20746f20 656e6372 797074 format.
But while decrypting, I get blank field (tried everything I knew). I am using following code for decrypting:
char *noteDet = (char *)sqlite3_column_text(statement, 1);
NSString *key = #"pass123";
NSString *secret = [NSString stringWithUTF8String:noteDet];
NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *clean = [secretData AES256DecryptWithKey:key];
aNote.note = ([[NSString alloc] initWithData:clean encoding:NSUTF8StringEncoding])?[[NSString alloc] initWithData:clean encoding:NSUTF8StringEncoding]:#"";
I think, I am unable to convert types. Please guide!
Thanks!
The description of NSData returns something like "" => if you were to read that again you would get different overall data ( and of a higher length ), also you are right that you are not converting the data types correctly.
Try saving the NSData object directly, by saving the bytes themselves rather than the description of the NSData object.
void *bytes = [dataObject bytes];
size_t length = [dataObject length];
Related
I'm developing an iOS app. I've come across a problem.
I am trying to send a hexString data through UDP to an wifi camera, which will response while getting correct data. My code is shown below. However I can't get any response from my wifi camera. (I'm using
https://github.com/robbiehanson/CocoaAsyncSocket)
NSString *sendMsg = #"6745000005000000000000000000000000000000000000001400000067450000140000000A";
NSData *bytes = [sendMsg dataUsingEncoding:NSUTF16BigEndianStringEncoding];
NSString *host = #"255.255.255.255";
[self.udpSocket sendData:bytes toHost:host port:ListenPort withTimeout:-1 tag:1];
Beside, I've try send my data through PacketSender (an app can send UDP data), which has a correct response.
enter image description here
Problem has been solved. The problem is while converting NSString to NSData. It's hex string which need to convert to NSData. Below is my code which works.
- (NSData *)dataFromHexString:(NSString *)hexString {
NSAssert((hexString.length > 0) && (hexString.length % 2 == 0), #"hexString.length mod 2 != 0");
NSMutableData *data = [[NSMutableData alloc] init];
for (NSUInteger i=0; i<hexString.length; i+=2) {
NSRange tempRange = NSMakeRange(i, 2);
NSString *tempStr = [hexString substringWithRange:tempRange];
NSScanner *scanner = [NSScanner scannerWithString:tempStr];
unsigned int tempIntValue;
[scanner scanHexInt:&tempIntValue];
[data appendBytes:&tempIntValue length:1];
}
return data;}
I have this code in Ruby which generates a Digital Signature based on an API KEY and some content, i have try to create some iOS code to replicate this but no success can someone help me out.
Ruby
key = "ZSyEULZSKlZS/SxjUbKG1cly10gyv68hvOeIYV6QLBM=".unpack('m*').to_s
hmac = HMAC::SHA256.new key
s = "some\nrandom\data\n"
hmac << s
ds_coded = [hmac.digest].pack('m*')
iOS
const char *cKey = [#"ZSyEULZSKlZS/SxjUbKG1cly10gyv68hvOeIYV6QLBM=" cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [#"some\nrandom\data\n" cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey),cData , strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSString *hash = NSString *hash = [HMAC base64EncodedStringWithOptions:0];
Both digital signature are always different. What can i change in my iOS code to make it the same as the Ruby code.
thanks
This what at the end worked for me.
NSData *saltData = [[NSData alloc] initWithBase64EncodedString:key options:0];
NSData *paramData = [somdata dataUsingEncoding:NSASCIIStringEncoding];
NSMutableData* hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH ];
CCHmac(kCCHmacAlgSHA256, saltData.bytes, saltData.length, paramData.bytes, paramData.length, hash.mutableBytes);
NSString *base64Hash = [hash base64EncodedStringWithOptions:0];
one,
I am getting string like this
"User_Name" = "\U0639\U0644\U0649 \U0639\U0628\U064a\U062f";
and when store in string then it show
على عبيد
Now I want to convert in and opposite manner like
على عبيد -------->"\U0639\U0644\U0649 \U0639\U0628\U064a\U062f"
I have use this code
NSData *data=[NSData dataWithBytes:[y_dict[key] UTF8String] length:strlen([y_dict[key]UTF8String])];
NSString* newStr = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(#"%#",newStr);
But it is not working.
How can I fix that issue?
Not sure why you want it, but here you are:
NSData *utf8 = [string dataUsingEncoding:NSUTF8StringEncoding];
NSMutableString *newStr = [[NSMutableString alloc] initWithCapacity:[utf8 length] * 6];
const uint8_t *bytes = [utf8 bytes];
for (NSUInteger i = 0; i < [utf8 length]; i++) {
[newStr appendFormat:#"\\U%04x", (unsigned)bytes[i]];
}
My code looks like this (using CommonCrypto/CommonHMAC.h):
- (NSString*) preperingCryptedData: (NSString*) data withKey: (NSString*) key {
NSData* dataToHash = [data dataUsingEncoding:NSUTF8StringEncoding];
NSData* keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"Utility: preperingCryptedData - Data to Crypt: %# and key %#\n...\n...\n...\n",dataToHash,keyData);
NSMutableData *dataHash = [NSMutableData dataWithLength:CC_SHA384_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA384, keyData.bytes, keyData.length, dataToHash.bytes, dataToHash.length, dataHash.mutableBytes);
NSString* readyString = [[NSString alloc] initWithData:dataToHash encoding:NSUTF8StringEncoding];
NSLog(#"Utility: preperingCryptedData call, result :%#\n...\n...\n...\n",readyString);
return readyString;
}
When I used code from: Here I got my string decoded without the Key. What am I doing wrong? How it's possible to encode message without the key?
There are two problem with the code:
1) You are using dataToHash as the output instead of dataHash.
2) dataHash is not a UTF8 data representation so it can not be successfully converted into a NSString.
Agree with the accepted answer. Provide working code.
- (NSString *)sha384:(NSString*)data withKey:(NSString *)key {
NSData* dataToHash = [data dataUsingEncoding:NSUTF8StringEncoding];
NSData* keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
unsigned char digest[CC_SHA384_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA384, keyData.bytes, keyData.length, dataToHash.bytes, dataToHash.length, digest);
NSString *sha384Str;
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA384_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA384_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
sha384Str = output;
return sha384Str;
}
I Want to save the image in Database and fetch the image in database.i am convert the image in NSData and the image is store successfully in database but when i fetch that image from database then it crash.it give this warning
Warning :- -[__NSCFString bytes]: unrecognized selector sent to instance 0x7916000
Below code For save the image in Database
NSData *dataImage1 = UIImagePNGRepresentation(image3.image);
NSString *str = [NSString stringWithFormat:#"Insert into Gallery(ImageName) VALUES ('%#')",dataImage1];
[Database executeQuery:str];
//Database.m
+(NSString* )getDatabasePath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"Database"];
return writableDBPath;
}
+(NSMutableArray *)executeQuery:(NSString*)str{
sqlite3_stmt *statement= nil;
sqlite3 *database;
NSString *strPath = [self getDatabasePath];
NSMutableArray *allDataArray = [[NSMutableArray alloc] init];
if (sqlite3_open([strPath UTF8String],&database) == SQLITE_OK) {
if (sqlite3_prepare_v2(database, [str UTF8String], -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
NSInteger i = 0;
NSInteger iColumnCount = sqlite3_column_count(statement);
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
while (i< iColumnCount) {
NSString *str = [self encodedString:(const unsigned char*)sqlite3_column_text(statement, i)];
NSString *strFieldName = [self encodedString:(const unsigned char*)sqlite3_column_name(statement, i)];
[dict setObject:str forKey:strFieldName];
i++;
}
[allDataArray addObject:dict];
[dict release];
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return allDataArray;
}
//Fetch image
NSString *str =[NSString stringWithFormat:#"Select * from Gallery where id = 1"];
NSMutableArray *arra =[Database executeQuery:str];
NSData *d =[[arra objectAtIndex:0] valueForKey:#"ImageName"];
UIImage *img = [[UIImage alloc] initWithData:d];
NSLog(#"%#",img);
Thanks in Advance
Your problem is that you cannot insert binary data by building a SQL statement with a stringWithFormat. You're inserting the NSData (binary data) into a field called ImageName, and you cannot use stringWithFormat to build that SQL statement.
Did you really mean to insert the image itself? In that case you'd use SQL like below, with a ? placeholder, and then use sqlite3_bind_blob for column number 1 with your NSData before you call sqlite3_step. Thus, the SQL would look like:
Insert into Gallery(ImageName) VALUES (?)
(As an aside, I'm not a fan of the choice of ImageName for the actual data of the image. I'd either use Image for the actual image data, or ImageName for the name of the image.)
And then, after preparing your SQL, you'd then call:
sqlite3_bind_blob(statement, 1, [dataImage1 bytes], [dataImage1 length], SQLITE_TRANSIENT);
You can then invoke sqlite3_step, like normal, to execute the SQL to insert the data.
When retrieving the data, after you successfully sqlite3_step, you'd use the appropriate sqlite3_column_blob functions:
const void *bytes = sqlite3_column_blob(statement, 0);
int len = sqlite3_column_bytes(statement, 0);
NSData *data = [NSData dataWithBytes:bytes length:len];
UIImage *image = [UIImage imageWithData:data];
Having said that, SQLite is notoriously inefficient in storing large blob data. You might want to store the image in the Documents folder and then just store the filename in your ImageName field.
i think you are getting bytes in string type in
[[arra objectAtIndex:0] valueForKey:#"ImageName"];
so first get string and then convert it to data.
try like this:
NSData* data = [[[arra objectAtIndex:0] valueForKey:#"ImageName"] dataUsingEncoding:NSUTF8StringEncoding];