How can I convert NSData to NSString without encoding to base64? - ios

I'm working on a game in Unity and I currently need to authenticate a apple user and receive some data, which apparently can only be done in native code. I found this code online, which works well, but some of the data is encoded in base64 and I need it decoded. I can try and decode it on the Unity side but it doesn't seem to work and it would be better to receive the raw data so I can work with it as I need.
The code is below:
[localPlayer fetchItemsForIdentityVerificationSignature:
^(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error)
{
if (error)
{
NSLog(#"ERROR: %#", error);
OnFailed([[error localizedDescription] UTF8String]);
}
else
{
NSString *signatureb64 = [signature base64EncodedStringWithOptions:0];
NSString *saltb64 = [salt base64EncodedStringWithOptions:0];
NSString *playerId = localPlayer.playerID;
NSString *alias = localPlayer.alias;
NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
OnSucceeded(
[[publicKeyUrl absoluteString] UTF8String],
timestamp,
[signatureb64 UTF8String],
[saltb64 UTF8String],
[playerId UTF8String],
[alias UTF8String],
[bundleId UTF8String]
);
}
}
];
The data I need decoded is the salt and the signature
If I'm not wrong, what I actually need is to convert from NSData to const char * as it is how the data is returned in the callback, instead of NSData to NSString as I wrote in the title, but I thought the title would sound better like that.
I believe what I need is relatively simple but most of my knowledge is in C# for Unity and some web stuff, so I'm a complete potato regarding cpp and apple in native code. Multiple solutions I found online either didn't compile or returned null.
Thanks in advance!

Related

NSData WriteToFile Fails while saving a photo from gallery through Share Extension

I am Writing an app which has share extension to save selected photo to my app' local storage from iphone photo gallery.
NSData WriteToFile returns YES but I couldn't find the stored file into the directory in of which I gave path while writing.
So, in short NSData WriteToFile fails to save a photo at given path.
Below is my code.
- (IBAction)acceptButtonTapped:(id)sender
{
__block UIImage *photo;
for (NSExtensionItem *item in self.extensionContext.inputItems)
{
for (NSItemProvider *itemProvider in item.attachments)
{
if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage])
{
[itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
if(image)
{
dispatch_async(dispatch_get_main_queue(), ^{
photo = image;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy_MM_dd_hh_mm_ss"];
NSString *fileName;
fileName = [NSString stringWithFormat:#"%#.jpeg",[formatter stringFromDate:[NSDate date]]];
dataPath = [dataPath stringByAppendingPathComponent:fileName];
NSData * imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0)];
BOOL isdone = [imageData writeToFile:dataPath atomically:NO];
NSLog(#"%u", isdone);
});
}
}];
break;
}
}
}
[self.extensionContext completeRequestReturningItems:#[] completionHandler:nil];
}
Any Help would be much appreciable.
Thank you.
If you're trying to access the Document directory from the share extension, NO you can't do that. Share extension or other widgets are separate application from their containing app and therefore have their own sandbox. So you will need to use App Groups to share files.
Application groups are primarily targeted for extensions, more specifically, for widgets.
NSFileManager has a method on it containerURLForSecurityApplicationGroupIdentifier: where you can pass in the identifier you created when turning on App Groups for your apps
NSURL *containerURL = [[NSFileManager defaultManager]
containerURLForSecurityApplicationGroupIdentifier:#"group.com.company.app"];
You can save the files to this location, because you can access the shared application groups from both extension and host app.
You're modifying dataPath on each pass through the loop, appending another filename to it. That will create an ever-growing series of badly formed paths that contain all the filenames.
Don't do that. Create a new local variable filePath, and construct a filename into filePath using
filePath = [docsPath stringByAppendingPathComponent: filename];
Log your path and LOOK AT IT. When your program doesn't behave as expected, don't trust any of your assumptions, because one or more of them may be wrong.

How to encrypt the NSString in ios locally

I am working on the static application that means no webservices. My application contains activation page so that we need to enter text inside that textfield to validate.
if([textfield.text isEqualToString:#"AKS_BI"]) {
//loading home screen
} else {
//show alert
}
For this one, I would like to encrypt the "AKS_BI" in order to hide the string while reverse engineering or Mat testing.
Can you anyone help me on this.
To encrypt:
//for best practise encrypting string length must be >=8
NSString *yourString=#"abcdefghij";
NSString *YourPasswordString = #"123456";//i've took static but you can set it dynamically
NSString *encryptPassword;
//Encrypt
NSData *data = [YourPasswordString dataUsingEncoding: NSASCIIStringEncoding];
NSData *encryptedData = [data AESEncryptWithPassphrase:yourString];
//Encode Base 64
[Base64 initialize];
encryptPassword = [Base64 encode:encryptedData];
For more details you can check here
Hope this helps.
You can use this library https://github.com/RNCryptor/RNCryptor.
However, you will still need to store the encryption key securely. For that I would recommend to split them up and perform some operation on them to combine.
Download AES encryption files from github. Download from here
After adding these downloaded files in your project now compare ,
if ([[AESCrypt encrypt:textfield.text password:[[NSBundle mainBundle] bundleIdentifier]] isEqualToString:ACTIVATION_STRING])
Here, ACTIVATION_STRING = hYjhuOO+GYTUBS05== .... This encrypted string needs to be created with the below syntax and make sure that remove the below syntax from code after generation of encrypted string,
NSString *encryptedData = [AESCrypt encrypt:#"AKS_BI" password: [[NSBundle mainBundle] bundleIdentifier]];
That's it. It simple.

NSString from NSData returns nil

So I am using Parse (which is pretty sweet) and I'm in the process of downloading files (short video files - no more then 1mb) from the parse server to my application to play. Now the way it works is (via documentation)..
PFFile* videoFile = [[tempArray objectAtIndex:i] objectForKey:#"track"];
[videoFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
NSString* dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSURL* videoURL = [NSURL URLWithString:dataString];
// now do something with this videoURL (i.e. play it!)
[data writeToFile:#"trackFile" atomically:YES];
NSURL *filePath = [NSURL fileURLWithPath:#"trackFile"];
NSLog(#"File Path: %#",filePath);
AVAsset* asset = [AVAsset assetWithURL:filePath];
AVPlayerItem* playerItem = [[AVPlayerItem alloc] initWithAsset:asset];
}
}
On download completion you are suppossed to create a string from the data and then a url from the string. Only problem is - the dataString always returns NULL/nil. I have confirmed that the data property is not empty and does in fact hold the video data. Why is this happening? Any help would be greatly appreciated. Thanks in advance!
I have confirmed that the data property is not empty and does in fact hold the video data.
Video data is not a UTF-8 string. It's definitely not a UTF-8 string representation of an URL. So when you say "interpret this video data as UTF-8," Cocoa rightly responds that it is not UTF-8 (because it's video data).
The simplest solution is to write this to disk, and then play the file.
Couple things that need to be determined first:
does the NSData object actually have any data, i.e., data.length > 0?
does the NSData object hold video data OR the url of the video data (not exactly clear)?
Making the assumption that the NSData object is holding the url and it's length is greater than 0, then you might want to try:
NSString* dataString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

Decrypting RSA with MIHCrypto (OpenSSL-Universal on iOS)

Hi I've got the a Problem with decrypting using MIHCrypto v0.3.2. These are my lines of code:
NSString *encrypted_text = #"BdhFH0sd7e9DExiCd50Ykh4spm2BX126skjJ1o8HHjKsN+J7r9IoI9kbB9AAacEpJsAfyesiJsq5gDBhQtcNbB6l88aSgPrEoVwR9ilzuzVcv1q3J1dxs4uIEMuhzoWT+R8//dD2jDdXPyFsdGWJc10CEizPFKpmy2jWhvU8CVs=";
NSBundle *myBundle = [NSBundle mainBundle];
NSString *privateKeyPath= [myBundle pathForResource:#"rsa_1024_priv" ofType:#"pem"];
NSData *privateKeyData = [[NSFileManager defaultManager] contentsAtPath:privateKeyPath];
MIHRSAPrivateKey *privateKey = [[MIHRSAPrivateKey alloc] initWithData:privateKeyData];
NSError *decryptionError = nil;
// decryption
NSData *encData = [encrypted_text dataUsingEncoding:NSUTF8StringEncoding];
NSData *decryptedEncData = [privateKey decrypt:encData error:&decryptionError];
NSString* decryptedText = [[NSString alloc] initWithData:decryptedEncData encoding:NSUTF8StringEncoding]; // iOS 7+, by iOS Core API
if(decryptionError){
DDLogDebug(#"error: %#",[encryptionError localizedDescription]);
}
DDLogDebug(#"decrypted: %#",decryptedEncData);
The problem is debugged here:
error: OpenSLL internal error! (Code=67522668,Description=error:0406506C:rsa routines:RSA_EAY_PRIVATE_DECRYPT:data greater than mod len)
Do you have any Idea?
I finally found a solution:
Using shorter Blocks of Data!
Background (posted by Hohl - here):
Using RSA with large blocks of data seems to be a common issue. Some
wrappers handle this by splitting the data into smaller blocks and
encrypting every block separately. But since RSA isn't intended to
encrypt large blocks of data this won't be implemented in this wrapper.
(Better combine RSA with something like AES if you need features of
both worlds.)

iPhone Unzip code

Really stuck on trying to write code to unzip a file or directory on the iPhone.
Below is some sample code that I'm using to try and unzip a simple text file.
It unzips the file but its corrupt.
(void)loadView {
NSString *DOCUMENTS_FOLDER = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *path = [DOCUMENTS_FOLDER stringByAppendingPathComponent:#"sample.zip"];
NSString *unzipeddest = [DOCUMENTS_FOLDER stringByAppendingPathComponent:#"test.txt"];
gzFile file = gzopen([path UTF8String], "rb");
FILE *dest = fopen([unzipeddest UTF8String], "w");
unsigned char buffer[CHUNK];
int uncompressedLength = gzread(file, buffer, CHUNK);
if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength || ferror(dest)) {
NSLog(#"error writing data");
}
else{
}
fclose(dest);
gzclose(file);
}
I wanted an easy solution and didn't find one I liked here, so I modified a library to do what I wanted. You may find SSZipArchive useful. (It can also create zip files by the way.)
Usage:
NSString *path = #"path_to_your_zip_file";
NSString *destination = #"path_to_the_folder_where_you_want_it_unzipped";
[SSZipArchive unzipFileAtPath:path toDestination:destination];
Has "sample.zip" really been created with gZip? The .zip extension usually is used for archives created by WinZip. Those can also be decompressed using zLib, but you'd have to parse the header and use other routines.
To check, have a look at the first two bytes of the file. If it is 'PK', it's WinZip, if it's 0x1F8B, it's gZip.
Because this is iPhone specific, have a look at this iPhone SDK forum discussion where miniZip is mentioned. It seems this can handle WinZip files.
But if it's really a WinZip file, you should have a look at the WinZip specification and try to parse the file yourself. It basically should be parsing some header values, seeking the compressed stream position and using zLib routines to decompress it.
This code worked well for me for gzip:
the database was prepared like this:
gzip foo.db
the key was looping over the gzread(). The example above only reads the first CHUNK bytes.
#import <zlib.h>
#define CHUNK 16384
NSLog(#"testing unzip of database");
start = [NSDate date];
NSString *zippedDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"foo.db.gz"];
NSString *unzippedDBPath = [documentsDirectory stringByAppendingPathComponent:#"foo2.db"];
gzFile file = gzopen([zippedDBPath UTF8String], "rb");
FILE *dest = fopen([unzippedDBPath UTF8String], "w");
unsigned char buffer[CHUNK];
int uncompressedLength;
while (uncompressedLength = gzread(file, buffer, CHUNK) ) {
// got data out of our file
if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength || ferror(dest)) {
NSLog(#"error writing data");
}
}
fclose(dest);
gzclose(file);
NSLog(#"Finished unzipping database");
Incidentally, I can unzip 33MB into 130MB in 77 seconds or about 1.7 MB uncompressed/second.
This code will unzip any .zip file into your app document directory and get file from app resources.
self.fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#"document directory path:%#",paths);
self.documentDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/abc", self.documentDirectory];
NSLog(#"file path is:%#",filePath);
NSString *fileContent = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"data.zip"];
NSData *unzipData = [NSData dataWithContentsOfFile:fileContent];
[self.fileManager createFileAtPath:filePath contents:unzipData attributes:nil];
// here we go, unzipping code
ZipArchive *zipArchive = [[ZipArchive alloc] init];
if ([zipArchive UnzipOpenFile:filePath])
{
if ([zipArchive UnzipFileTo:self.documentDirectory overWrite:NO])
{
NSLog(#"Archive unzip success");
[self.fileManager removeItemAtPath:filePath error:NULL];
}
else
{
NSLog(#"Failure to unzip archive");
}
}
else
{
NSLog(#"Failure to open archive");
}
[zipArchive release];
It's really hard to unzip any arbitrary zip file. It's a complex file format, and there are potentially many different compression routines that could have been used internally to the file. Info-ZIP has some freely licencable code to do it (http://www.info-zip.org/UnZip.html) that can be made to work on the iPhone with some hacking, but the API is frankly horrible - it involves passing command-line arguments to a fake 'main' that simulates the running of UnZIP (to be fair that's because their code was never designed to be used like this in the first place, the library functionality was bolted on afterwards).
If you have any control of where the files you're trying to unzip are coming from, I highly recommend using another compression system instead of ZIP. It's flexibility and ubiquity make it great for passing archives of files around in person-to-person, but it's very awkward to automate.
zlib isn't meant to open .zip files, but you are in luck: zlib's contrib directory includes minizip, which is able to use zlib to open .zip files.
It may not be bundled in the SDK, but you can probably use the bundled version of zlib use it. Grab a copy of the zlib source and look in contrib/minizip.
I haven't used the iPhone, but you may want to look at GZIP, which is a very portable open source zip library available for many platforms.
I had some luck testing this on the iPhone simulator:
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *saveLocation =
[documentsDirectory stringByAppendingString:#"myfile.zip"];
NSFileManager* fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:saveLocation]) {
[fileManager removeItemAtPath:saveLocation error:nil];
}
NSURLRequest *theRequest =
[NSURLRequest requestWithURL:
[NSURL URLWithString:#"http://example.com/myfile.zip"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSData *received =
[NSURLConnection sendSynchronousRequest:theRequest
returningResponse:nil error:nil];
if ([received writeToFile:saveLocation atomically:TRUE]) {
NSString *cmd =
[NSString stringWithFormat:#"unzip \"%#\" -d\"%#\"",
saveLocation, documentsDirectory];
// Here comes the magic...
system([cmd UTF8String]);
}
It looks easier than fiddling about with zlib...

Resources