Encode and Decode a string on Objective C - objective-c

I use below code to encode and decode a string on objective C. The encoding is good, I debug and see that it throw a hash string when input is #"1". But when I try to decode this hash string, it return nil.
Please help me.
+(NSString *)encrypt: (NSString*) input
{
//Base64 Encoding
char base64Result[32];
size_t theResultLength = 32;
Base64EncodeData(input, 20, base64Result, &theResultLength);
NSData *theData = [NSData dataWithBytes:base64Result length:theResultLength];
NSString *base64EncodedResult = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
NSString* decryptedString = [self decrypt:base64EncodedResult];
return [base64EncodedResult autorelease];
}
+ (NSString *) decrypt:(NSString*) input{
Byte inputData[[input lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];//prepare a Byte[]
[[input dataUsingEncoding:NSUTF8StringEncoding] getBytes:inputData];//get the pointer of the data
size_t inputDataSize = (size_t)[input length];
size_t outputDataSize = EstimateBas64DecodedDataSize(inputDataSize);//calculate the decoded data size
Byte outputData[outputDataSize];//prepare a Byte[] for the decoded data
Base64DecodeData(inputData, inputDataSize, outputData, &outputDataSize);//decode the data
NSData *theData = [[NSData alloc] initWithBytes:outputData length:outputDataSize];//create a NSData object from the decoded data
NSString *result = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
return [result autorelease];
}

In you encoding method, you have to convert the input string to a byte buffer and feed that to Base64EncodeData:
NSData *inputData = [input dataUsingEncoding:NSUTF8StringEncoding];
Base64EncodeData([inputData bytes], [inputData length], base64Result, &theResultLength, NO);
(The NSString *input argument in the encoding method points to an Objective-C structure, not to a C string. So your encoding method seems to work. It encodes something, but not the input string. The decoding method then fails at
NSString *result = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
because the decoded data does not contain valid UTF-8.)

Related

What is wrong with this code implementation? Objectice-c, IOS

Testing the relationship between NSData, NSMutableData And bytes method and Byte Type variables want to change NSData Value to Bytes, when i run this it crashes the app but doesnt throw any error..
This Runs Ok
NSData *myData = [[NSData alloc] initWithData:someData];
Byte *finalValue = (Byte *)[myData bytes];
But This throws crashes app and doesnt throw an error
NSData *myData = [[NSData alloc] initWithData:someData];
NSMutableData *testingWaters = (NSMutableData *)[myData bytes];
Byte *finalValue = (Byte *)[testingWaters bytes];
EDITED: Keep In mind i want to convert a NSData Variable or NSMutableData Variable into a Byte variable.
You can create a mutable copy of myData
NSData* someData = [[NSString stringWithFormat:#"HELLO WORLD"]dataUsingEncoding:NSUTF8StringEncoding];
NSData *myData = [[NSData alloc] initWithData:someData];
NSMutableData *testingWaters = (NSMutableData *)[myData mutableCopy];
Byte *finalValue = (Byte *)[testingWaters bytes];

Conversion from decrypted NSData to NSDictionary fails

I have to encrypt and scramble a NSDictionary and then unscramble and decrypt in another method. I have followed the instructions from Securely storing keys in iOS Application except that I'm not using a PLIST file to fill the NSDictionary values, but NSString values that are being inputed in the program and I'm doing this targeting OSX
The program can be divided in 3 parts:
Encryption: Encrypts the NSDictionary and returns a base64encoded NSString
Scramble: Scrambles the base64encoded key among the values of the previous NSString
Unscramble and Decryption
My problem is in the last decryption. The unscramble works just fine, but the decryption seems to produce NSData that can't be convertible into the original NSDictionary
Encryption
What I'm doing for encryption is:
Initialising a NSDictionary
Converting it to NSData via NSPropertyListSerialization and format NSPropertyListXMLFormat_v1_0
Encrypting this data using RNCryptor and a key
Returning the base64 representation of this NSData as NSString
The code for this part is:
+(NSString *)encrypt:(NSString *)firstValue secondValue:(NSString *)secondValue andKey:(NSString *)key;
{
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjects:[[NSArray alloc] initWithObjects:firstValue, secondValue, nil] forKeys:[[NSArray alloc] initWithObjects:#"first", #"second", nil]];
NSData *data = [NSPropertyListSerialization dataFromPropertyList:dictionary format:NSPropertyListXMLFormat_v1_0 errorDescription:nil];
NSData *encryptData = [RNEncryptor encryptData:data withSettings:kRNCryptorAES256Settings password:key error:nil];
return [encryptData base64EncodedString];
}
Scramble
The second part of the process is to scramble the key in base64 among the characters of the data, I'm doing this by:
Converting the key to NSData using -(NSData *)dataUsingEncoding:
Converting this NSData to a base64encoded NSString
Inserting char of this NSString into a NSMutadedString in a particular order
Returning NSString from this NSMutadedString to be decrypted later
Here's the code for the scramble part:
+(NSString *)scrambleStrings:(NSString *)firstValue secondValue:(NSString *)secondValue andKey:(NSString *)key;
{
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
key = [keyData base64EncodedString];
// String from the first method
NSString *encrypt = [self encrypt:firstValue secondValue:secondValue andKey:key];
NSArray *myOrder = [self mySortAlgorithm:key];
NSMutableString *mutableEncrypt = [NSMutableString stringWithString:encrypt];
for(int i=0; i<[myOrder count];i++)
{
unichar c = [key characterAtIndex:i];
int index = [[myOrder objectAtIndex:i] intValue];
[mutableEncrypt insertString:[NSString stringWithCharacters:&c length:1] atIndex:index];
}
return [NSString stringWithString:mutableEncrypt];
}
Decryption
The third part consists of testing if I can decrypt and unscramble it to the original NSDictionary and NSString key. It basically consists of:
Retrieve the scrambled NSString from the second method
Separating the scrambled key from the dictionary NSData from the previous NSString
Decode the base64encode key (Works for sure 'till here)
Decode the base64encoded dictionary data
Decrypt the previous data using RNCryptor using the decoded key
Initialising a NSDictionary using the data from the last step
Output the NSDictionary values via NSLog
And Here's the code for this last part:
+(BOOL)testScrambleWithFirstValue:(NSString *)firstValue secondValue:(NSString *)secondValue andKey:(NSString *)key;
{
NSString *scrambledAndEncryptedKeys = [self scrambleFirstValue:firstValue secondValue:SecondValue andKey:key];
NSArray *myOrder = [self mySortAlgorithm:key];
NSMutableString *encryptedDictionary = [[NSMutableString alloc] init];
NSMutableString *encryptedKey = [[NSMutableString alloc] init];
for (int i=0; i<scrambledAndEncryptedKeys.length; i++) {
char c = [scrambledAndEncryptedKeys characterAtIndex:i];
if ([myOrder doesContain:[NSNumber numberWithInt:i]]) {
[encryptedKey appendFormat:#"%c", c];
} else {
[encryptedDictionary appendFormat:#"%c",c];
}
}
NSString *decryptedKey = [[NSString alloc] initWithData:[NSData dataFromBase64String:[NSString stringWithString:encryptedKey]] encoding:NSUTF8StringEncoding];
NSString *base64DataStr = [[NSString alloc] initWithData:[NSData dataFromBase64String:[NSString stringWithString:encryptedDictionary]] encoding:NSUTF8StringEncoding];
NSData *decryptedData = [RNDecryptor decryptData:[base64DataStr dataUsingEncoding:NSUTF8StringEncoding] withPassword:decryptedKey error:nil];
NSPropertyListFormat xmlFormat;
NSDictionary *decryptedDictionary = [NSPropertyListSerialization propertyListWithData:decryptedData options:NSPropertyListImmutable format:&xmlFormat error:nil];
//Outputs NULL
NSLog(#"decryptedDictionary:%#", decryptedDictionary);
//Just to simplify I'm returning YES here
return YES;
}
The problem is, that the last NSLog outputs a NULL value. Which makes me think that the NSData is not being decrypted.
I've been hammering my head over this since yesterday morning, so all the help is appreciated. Thanks in advance

NSString from NSData always null

I would like to sign a request with HMAC SHA512, but I seem to mess up encoding and decoding from and to NSData and NSString. I desperately tried to figure out what is wrong, but I just don't seem to get it right.
PSEUDOCODE:
function hmac_512(msg, sec) {
sec = Base64Decode(sec);
result = hmac(msg, sec, sha512);
return Base64Encode(result);
}
secret = "7pgj8Dm6";
message = "Test\0Message";
result = hmac_512(message, secret);
if (result == "69H45OZkKcmR9LOszbajUUPGkGT8IqasGPAWqW/1stGC2Mex2qhIB6aDbuoy7eGfMsaZiU8Y0lO3mQxlsWNPrw==")
print("Success!");
else
printf("Error: %s", result);
My implementation:
+(void)doSomeMagic{
NSString *message = #"Test\0Message";
NSString *signedRequest = [self signRequestForParameterString:message];
//checking against CORRECT (from JAVA equivalent) signed request
if ([signedRequest isEqualToString:#"69H45OZkKcmR9LOszbajUUPGkGT8IqasGPAWqW/1stGC2Mex2qhIB6aDbuoy7eGfMsaZiU8Y0lO3mQxlsWNPrw==" ])
NSLog(#"Success!");
else
NSLog(#"Error!");
}
Here is the signing method:
+(NSString *)signRequestForParameterString:(NSString*)paramStr{
NSString *secret = #"7pgj8Dm6";
// secret is base64 encoded, so I decode it
NSData *decodedSecret = [secret base64DecodedData];
NSString *decodedSecretString = [NSString stringWithUTF8String:[decodedSecret bytes]];
NSData *data = [paramStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *dataString = [NSString stringWithUTF8String:[data bytes]];
return [self generateHMACSHA512Hash:decodedSecretString data:dataString];
}
Here is the hashing function:
+(NSString *)generateHMACSHA512Hash:(NSString *)key data:(NSString *)data{
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
length:sizeof(cHMAC)];
NSString *hash = [HMAC base64EncodedString];
return hash;
}
I am pretty sure it is due to the encoding of the strings (decodedSecretString and dataString). decodedSecretString (decoded base64) after decoding is encoded in ASCII. However, when I call the hashing method, I encode it in ascii again, which will result in a null error. Everything is confusing me right now.
Your secret doesn't decode to a valid UTF-8 string, and Java allows NUL bytes in strings, but when you're converting "Test\0Message" to a C string and using strlen, its length is 4.
Something like this should work:
+(NSString *)signRequestForParameterString:(NSString*)paramStr{
NSString *secret = #"7pgj8Dm6";
NSData *data = [paramStr dataUsingEncoding:NSUTF8StringEncoding];
return [self generateHMACSHA512Hash:[secret base64DecodedData] data:data];
}
+(NSString *)generateHMACSHA512Hash:(NSData *)key data:(NSData *)data{
unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, key.bytes, key.length, data.bytes, data.length, cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
return [HMAC base64EncodedString];
}
When doing HMAC or other cryptographic functions, you should build up some fundamental methods/functions that don't deal with strings first. Then you can create wrapper methods that decode/encode string data or digests in a convenient way.
+ (NSData *)dataBySigningData:(NSData *)data withKey:(NSData *)key
{
unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, [key bytes], [key length], [data bytes], [data lenght], cHMAC);
return [[NSData alloc] initWithBytes:cHMAC length:CC_SHA512_DIGEST_LENGTH];
}
+ (NSData *)dataBySigningMessage:(NSString *)message withKey:(NSData *)key
{
return [self dataBySigningData:[message dataUsingEncoding:NSUTF8StringEncoding]
withKey:[key dataUsingEncoding:NSUTF8StringEncoding]];
}
(Note: this code is not tested, just hacked together in a text editor)
Don't worry about the string representation of your key or data. Then you can go from there, e.g. getting the base64 encoding of the digest.
Cryptographic functions DO NOT CARE about strings or text encodings. They care about bytes. Strings (in C, since they are null-terminated) are a mere subset of what can be represented in data. So it would be severely limiting to deal with strings.

How to encode NSData raw bytes directly to UTF-16 (Unicode)?

Environment: iOS Xcode Objective-C Garbled Unicode UTF-16
My Question:
I got the file content from a remote file and then stored it into NSData object, then I want to convert the NSData to Unicode encoding (note: not UTF-8,UTF-16 will okay), the problem is that I do not know the original file content encoding, what can I do to convert the unknown raw bytes into Unicode (UTF-16)?
I have tried so many method, but no one successfully touch my target, the code:
NSData *chunk = [NSData dataWithContentsOfURL:url];
NSString* newStr = [[[NSString alloc] initWithData:chunk encoding:NSUTF16LittleEndianStringEncoding] autorelease];
NSData* d = [newStr dataUsingEncoding:NSUnicodeStringEncoding];
[d writeToFile:newFilePath atomically:YES];
got the file into NSData, encode it into Unicode and write to file.
NSString* converted_str = [[NSString alloc] initWithData:chunk encoding:NSUTF8StringEncoding];
NSData * d = [(id)CFStringCreateExternalRepresentation(NULL, (CFStringRef)converted_str, kCFStringEncodingUnicode, 0) autorelease];
[d writeToFile:newFilePath atomically:YES];
convert the NSData to NSString, then restore it into NSData for write to file, not work.
[converted_str writeToFile:newFilePath atomically:YES encoding:NSUnicodeStringEncoding error:&error];
write to file directly using NSString object, garbled.
CFStringRef converted_str = CFStringCreateWithBytes(NULL, [chunk bytes],[chunk length], kCFStringEncodingUTF8,false);
CFStringRef newStr = [chunk dataUsingEncoding:NSUTF8StringEncoding];
NSData * d = [(id)CFStringCreateExternalRepresentation(NULL, (CFStringRef)big5Str, NSUnicodeStringEncoding, 0) autorelease];
[d writeToFile:newFilePath atomically:YES];
Using cString to do the encoding work, but also failure.
char converted[([chunk length] + 1)];
[chunk getCString:converted maxLength:([chunk length] + 1) encoding: NSWindowsCP1251StringEncoding];
NSLog(#"converted:%s", converted);
NSString *converted_str = [NSString stringWithCString:converted encoding:NSUnicodeStringEncoding];
NSLog(#"converted_str:%#", converted_str);
I also using usedEncoding:&xxx to get the original file encoding, then try to decode it into string object using the returned encoding, ..., failure again.
NSStringEncoding encoding;
NSString *chunk = [[NSString alloc] initWithContentsOfURL:[rb fileURL] usedEncoding:&encoding error:&error];
...
I then try to using kCFStringEncodingUTF16 to get the Unicode encoded buffer, but failure.
NSStringEncoding encode = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF16);
NSString *chunk = [NSString stringWithContentsOfURL:url encoding:encode error:&error];
In the end, I want to try libiconv for iOS( iPhone,iPad), but the trouble is the encoding of source content is unknown, the usedEncoding:&xxx function can not always work.
I have no idea of this trouble ... :(
Is there someone meet the similar question, please give me some direction, any answer will be most appreciated , thank you.
Sincerely wishing you and your family happiness and health.

convert base64 decoded NSData to NSString

I'm trying to encode and decode base64 data. but while decoding the base64 data, it returns bunch of hex values, but i couldn't display or printout using NSlog to the original readable strings. The below code couldn't print anything, just empty.
Can anyone help ? thanks
>
>
NSString* msgEncoded = [[NSString alloc] initWithFormat:#"Q1NNKE1DTC9TTUEgUkNWL2FkbWluQHNldGVjcy5jb20gT1JHLyBUVkIvNDNkYzNlMzQwYWQ3Yzkp:"];
NSData* decoded = [[NSData alloc] initWithData:[self decodeBase64WithString:msgEncoded]];
NSString* plainString = [[NSString alloc]initWithData:decoded encoding:NSUTF8StringEncoding];
NSLog(#"\n Decoded string: %# \n", plainString );
There is a built in function in NSData
[data base64Encoding];
[data base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
If you are still having issues, try out this library: https://github.com/l4u/NSData-Base64
use it like so:
#import "NSData+Base64.h"
NSData *someData //load your data from a file, url or photo as needed
NSData *file = [NSData dataWithContentsOfFile:#"mytextfile.txt"];
NSData *photo = UIImageJPEGRepresentation(self.photo.image,1);
//encode it
NSString *base64string = [photo base64EncodedString];
NSString *base64file = [file base64EncodedString];
//decode it
NSData *back = [NSData dataFromBase64String:base64string];
Try Google's GTMStringEncoding class. You'll need GTMDefines.h too.
GTMStringEncoding *coder = [GTMStringEncoding rfc4648Base64StringEncoding];
NSString *encodedBase64 = [coder encodeString:#"Mary had a little lamb"];
// will contain the original text
NSString *decodedText = [coder decodeString:encodedBase64];
To encode NSData* to NSString* and back to NSData*, use the encode: + decode: methods instead of encodeString: + decodeString:.
As a bonus you get a lot of additional useful encodings, such as the url-safe variant of Base64.