iOS AES encryption wrong result - ios

Here is how I encrypt the string:
+ (NSString *)encrypt:(NSString *)message password:(NSString *)password {
NSData *encryptedData = [[message dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptedDataUsingKey:[password dataUsingEncoding:NSUTF8StringEncoding] error:nil];
NSString *base64EncodedString = [NSString base64StringFromData:encryptedData length:[encryptedData length]];
return base64EncodedString;
}
The plain text is:
{"roomID":"{\"array\":[\"949156\",\"949157\"]}","duration":15,"link":"","type":"text","thumbnailBlobID":"","posy":103.6809424405021,"text":"Aa","className":"Message","originalBlobID":"","datetime":"20140319214528457","selfDestructive":0,"userID":"949157","posx":1.347154229880634,"status":"normal","entityID":"20140319214528457and949157and{\"array\":[\"949156\",\"949157\"]}"}
This is what I get
gXqxfDhImRD7S20lUdYuCPAlXfqRnG6xk4w4K5Op/WnYMh6VgJUUqMifK2vHkUpAbnZ+wKdSWjfzU1PuOwvJ4dJ9EiHwjeyyorezFNG6eylYcOvMWNeU6+5Z9XxfcFngqhmxM6k1lf7bkttTu0FnEHad/czFgiMVTy60DJpFMLSODkKEVezqQB9s/f3Qy/B6+sF5Hs5E0FDn7kU6Jtm6mLkFjGzDCXTdFXNjdussbkTL8C1gcOnn4hrNkqQKb82MgqqYf8sVgs4FVIjsmoJd0ALY8y/5QbBkgc6ZyB4aOQPPx/u4HS3F7HXHkIkkAjZS/hiHQBRyfwCvi2uwFedno5twYogNW56pSMQqBeJBxBAhPMpXzb51853GLP4bCotGtOyEfU96x5kWHDOR5QA2WhYZkB3AALDJ2kfqzWR8iOKHo3zE6DCQ7aH0RwEFlNPi8vsNwvUqtQ7nUODA5lUMYah6W2rfDh/em8BD8dGF5J6IUTIlSerx8wWPA9bn/SxO
From website http://aesencryption.net (256 bit)
(Which i assume to be the correct answer
5MdV0TelF++/8Cy9bnkeah0nQ5JbC04CEdCcHfdlavQtZaxg3ZSXklp9yXbeP05hcIeQDgFcMr9NlD6aKhjBL3Xh70ksYqc6Xv5BZvCbXrvO4ufAf4gjmDRQr9DYSbjFct6N82fFGDtrcuFm36Zv+QAQtR/scT86A++Vn/EBlPwFb7ZmxlMPkJWjQ98ObreXHeKkZ8f2npMKfJ0i36nIZ8CZeL0EYeg/njo9ykPTfm9wfKieqlIICn1qNZAXE//P9hTleW/GNs5+ET2gxNSCmdO+ByUB9Q3sZ/+57qXbsfCxHr8dsuBrsbRI+cVIXyquQL1IC/zuz3G3fcyoiLrD/PnFtV5z5XR0hpUiU8JjovjYwyXaBfyTBnO71zxmdoZdsyPwA1LQO0pedn8UsICT2KbfBKwuumW2CJPexbnMmVzpIJ/VPISikdg18V3rdJqiPMIb4Zq2PGKO0Wtq1dCTMusTv/ZnqxgVQFQlUivgBqtnOLCDaMAGL636NXda95V2

There is no single standard way to apply AES, or standard data format for the output. AES requires a number of helpers when used on data that is not exactly 16-bytes long, and they can be configured in different ways. I have no idea how the aesencryption.net tool is applying these helpers; it doesn't say. If AES256EncryptedDataUsingKey: is the particular piece of code I assume it, it applies them very poorly (it's very similar to the code I discuss in Properly Encrypting With AES With CommonCrypto). I would not be surprised if aesencryption.net does something different.
If you have a piece of plaintext and a key, and you pass it to an encryptor twice and get the same answer back, then your encryptor is broken. A correct AES encryptor (for almost any common use of AES) should always return different results for the same plaintext+key (otherwise an attacker can determine that two plaintexts are equal, which breaks the security proof of AES). In the most common case, this is achieved by having a unique initialization vector (IV). For password-based AES, you also include a random salt. So even if these were good implementations of AES, you wouldn't expect your results to match.

Is it possible that the escape characters (the back slashes) are being interpreted differently in code versus via the web? The bottom line here is I would (in code) decode what you just encoded and you should come out with the same as what you put in. This is probably the test you want to conduct. Hope this helps. Also see comment below from #RobNapier

Related

iOS: Storing Non-User password

I need to store third-party username/password in my iOS application, what is the best and most secure way to do this? When my app first runs, it will need to talk to Google's Picasa to download private pictures to use for the app. To talk to Picasa, I have to provide my username/password and storing in the code is not secure at all.
I've search the web, I see Keychain came up a lot, but how exactly do I pre-load my password into keychain?
Is there a configuration file in xCode somewhere to store passwords needed for web-services?
Thanks
Think that you need to store the password in encrypted form. Pick some encrypting algorithm, generate the encrypted details. And in code have some method to decrypt it when needed.
You just don't want someone who would read your code as plain text to see the password.
Think that something as simple as splitting the password into separate strings and later joining them could be enough.
Here for example You have encrypted in code "My1Password":
#define R1 #"My"
#define R2 #"Password"
+ (NSString *)generatePass{ return [NSString stringWithFormat:#"%#%#%#, R1, #(1), R2]; }
This is a response to krzysztof above:
I'm in a catch-22 situation here as I can't seem to grasp the concept of feeding the password as parameter to another function. Aside from avoid others reading the source code in plain text, can't hackers obtain the binary file and reverse engineer to read the password in the source code (R1 & R2 in this case)???
Back to encryption, lets take the following line of code which Encrypt/Decrypt data:
NSData *encryptedImage = [RNEncryptor encryptData:imageData withSettings:kRNCryptorAES256Settings password:#"A_SECRET_PASSWORD" error:nil];
NSData *decryptedData = [RNDecryptor decryptData:data withSettings:kRNCryptorAES256Settings password:#"A_SECRET_PASSWORD" error:nil];
This is where I'm stuck... where do I store A_SECRET_PASSWORD?

ios issue with stringByAddingPercentEscapesUsingEncoding

In my app I need to send some parameters to the url, when I am trying with the stringByAddingPercentEscapesUsingEncoding it is not converting correctly. If I am not using this encoding I am getting null(Exception) from the nsurl.Here is me code.
http://www.mycompurl.co?message=xyz&id=____ here I am sending the id 1 or 2 or any number.
when I convert this string to url by using stringByAddingPercentEscapesUsingEncoding I got
"http://www.mycompurl.co?message=xyz&id=**%E2%80%8B**1" (when I send 1 as parameter). Then I got the 0 data from the Url.
str = [NSString stringWithFormat:#"%#?message=xyz&id=​%#",Application_URL,bootupdateNew];
str = [str stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
url=[NSURL URLWithString:str];
NSError* error = nil;
data1 = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
Thank you In advance
Basics
A URL is composed of several components.
Each component has its own rule how the component's source string must be encoded, so that this component becomes valid within the URL string.
Applying stringByAddingPercentEscapesUsingEncoding: will never always produce a correct URL if the string consists of more than one component (and if we assume, we have an unbounded set of source strings - so that the encoded string actually differs from the source string).
It even won't work always with a string which represents any single component.
In other words, for what's worth, stringByAddingPercentEscapesUsingEncoding: should not be used to try to make a URL out of several components. Even getting the URL query component correctly encoded is at least error prone, and when utilizing stringByAddingPercentEscapesUsingEncoding: it still remains wonky. (You may find correct implementations on SO, though - and I posted one myself).
But now, just forget about it:
It took awhile for Apple to recognize this failure, and invented NSURLComponents. It's available since iOS 7. Take a look! ;)

Data encryption with AES

I'm building an app that will communicate with a server (php), and this communication (probably will be with json) i want to encrypt. After a lot of searching and reading i found the AESCrypt-Objc project.
While testing the encryption (i'm using a web tool AES Encryption test) i found that in the encryption result i'm missing 16 byte of data.
Here's the example i'm using
In the AES project:
String to be encrypted: "The quick brown fox jumped over the lazy dog".
Password: "12345678901234561234567890123456"
The result:
<7eda336b 82f3e279 ae7638fe cccfffc6 5fbef8da 6df76d97 67d8cfa8 5bce2ae9>
My Code:
self.strnToBeEnc = #"The quick brown fox jumped over the lazy dog";
self.appKey = #"12345678901234561234567890123456";
NSData *data2 = [self.strnToBeEnc dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#", data2);
NSData *s2 = [data2 AES256EncryptedDataUsingKey:self.appKey error:nil];
NSLog(#"%#", s2);
WEB Tool:
Same string and password
The result:
<7eda336b 82f3e279 ae7638fe cccfffc6 5fbef8da 6df76d97 67d8cfa8 5bce2ae9 ca2ed34a 48f85af2 909654d5 b0de0fb7>
As you can see i'm missing some bytes...:)
I've tried adding to the buffer in the algorithm, but with no success.
Any advice?
Thanks
(if the question is not Detailed enough please let me know)
I know you were trying to avoid this but I think you might need to spend some time in the source code of AESCrypt-Objc as I suspect it is somehow not encrypting the last block.
Step into the code and see if you actually get to the CCCryptorFinal call, and note its results. This can be found in the AESCrypt-ObjC/NSData+CommonCrypto.m _runCryptor:result: . Another thing to look into is the default padding type they are using which appears to be kCCOptionPKCS7Padding this will also have an effect on your ending bytes.
Do your testing first with non-arbitrary length bytes that are multiples of the AES block size, then once you have validated that move on to the variable length ones you have here.

decoding a HUGE NSString, running out of memory

I'm looking for ideas on how to improve a process of decoding a 40+MB NSString with base64 encoding and saving it to a file while being able to fit the process into iPad 1's 256 MB of RAM
I get the NSString from NSXMLParser:
id pointerToString;
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"myElement"])
{
pointerToString = [string retain];
}
}
Then I use the pointerToString in a callback:
[handler performSelector: action withObject: pointerToString];
In the callback (id value is the pointerToString). I initialize NSData with the pointerToString while decoding it with base64 encoding.
^(id value)
{
if ( [[value class] isSubclassOfClass:[NSString class]] )
{
NSData *data = [NSData dataFromBase64String:value];
[data writeToFile:file.path atomically:YES];
}
}
the iPad 1 device runs out of memory and gets killed by the iOS when the memory allocation reaches around 130MB after or during the NSData call.
I have determined that in order to process the 40+MB NSString this way, I'd need about 180+MB of RAM (this is what the maximum memory allocation is on iPad 2 & 3, where the process works because of more RAM)
Any ideas/tips ?
Thank you
Edit:
When dealing with a file of this size, you probably do not want to load the entire multi-megabyte file in memory at one time, neither the huge input file nor the almost-as-huge output file. You should be parsing this in a streaming fashion, decoding the data in your foundCharacters as you go along, not holding any significant portions in memory.
The traditional techniques, though, may hold your entire XML file memory in three phases of the process:
As you download the XML file from the server;
As the XML parser parses that file; and
As you do the Base64-decode of the file.
The trick is to employ a streaming technique, that does these three processes at once, for small chunks of the single, large XML file. Bottom line, as you're downloading the entire 50mb file, grab a few kb, parse the XML, and if you're parsing the Base64-encoded field, perform the Base64-decode for that few kb, and the proceed to the next chunk of data.
For an example of this (at least the streaming XML downloading-and-parsing, not including the Base64-decoding), please see Apple's XMLPerformance sample project. You'll see that it will demonstrate two XML parsers, the NSXMLParser that we're all familiar with, as well as the less familiar LibXML parser. The issue with NSXMLParser is that, left to it's own devices, will load the entire XML file in memory before it starts parsing, even if you use initWithContentsOfURL.
In my previous answer, I mistakenly claimed that by using initWithContentsOfURL, the NSXMLParser would parse the URL's contents in nice little packets as they were being downloaded. The foundCharacters method of NSXMLParserDelegate protocol seems so analogous to the NSURLConnectionDelegate method, didReceiveData, that I was sure that NSXMLParser was going to handle the stream just like NSURLConnection does, namely returning information as the download was in progress. Sadly, it doesn't.
By using LibXML, though, like the Apple XMLPerformance sample project, you can actually use the NSURLConnection ability of streaming, and thus parse the XML on the fly.
I have created a little test project, but I might suggest that you go through Apple's XMLPerformance sample project in some detail. But in my experiment, a 56mb XML file consumed well over 100mb when parsing and converting via NSXMLParser but only consumed 2mb when using LibXML2.
In your comments, you describe the desire to download the Base64-encoded data to a file and then decode that. That approach seems a lot less efficient, but certainly could work. By the way, on that initial download, you have the same memory problem (that I solve above). I urge you to make sure that your initial download of the Base64-encoded data does not blithely load it into RAM like most routines do. You want to, assuming you're using NSURLConnection, write the data to the NSOutputStream as you receive the data in didReceiveData, not hold it in RAM.
See the didReceiveResponse in AdvancedGetController.m of Apple's AdvancedURLConnections example for an example of how to write a file as it's being received, rather than typical patterns of adding it to a NSMutableData (because most of these routines just assume you're dealing with a reasonably sized file). (Ignore all the stuff in that AdvancedURLConnections sample about authentication and the like, but focus on understanding how it's writing to the NSOutputStream as it goes.) This technique will address the first of the three problems listed at the top of this answer, but not the latter two. For that, you'll have to contemplate using LibXML2 as illustrated in Apple's XMLPerformance sample project, or other similar techniques.
The method
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
is probably not receiving all the data at once.
Doc is saying
"Sent by a parser object to provide its delegate with a string representing all or part of the characters of the current element."
So it is called multiple times.
It looks like you are trying to write the whole string at once (sorry if I am wrong).
So you could append the received data to the file by doing the following:
You can use a combination of
-writeData:
and
-seekToEndOfFile
methods from NSFileHandle class for writing NSData to the end of a file.
But be carefull with your base64 encoding on partial data receivment!

PGP decryption on iOS

I'm trying to implement decryption of a PGP file on an iPad. I set up some test .txt files which I then encrypted via PGP desktop.
I've imported the private key of the certificate used to encrypt the document, using SecPKCS12Import, then SecIdentityCopyPrivateKey() from the resulting SecIdentityRef.
If I test encrypting and decrypting a simple string in Objective C, using the public and private key of the cert, that works perfectly.
Now that I'm trialling the actual PGP decryption, I'm a bit stumped... Reading the text from the .pgp file, I get:
-----BEGIN PGP MESSAGE-----
Version: 10.1.1.10
qANQR1DBwEwDraQm2Kxa5GkBB/4yLebeLk10C2DVvHpQL20E0DThhgQlTasXo+YJ
pLp5Ig2hHu4Xx0m74D3vfyWpA2XQA02TMAHO9lhNfkE234c/ds05D1UyQkJEoqW+
joEcbRT5rlGN3qrMf1FXv8/01EHH0dgeD6mAkkDeDEorIirYHCF6+QVkedaphZLs
c63GmcikzkWZT/vv20ICL3Ys0DaC3P9zu0T1GtjkmQ062kaTab/VBJnQrsY/y1JU
ypmbW9bbFeZMcAqXHMqpjw49K5UluIJaDbRNAjIvHTFLNuOYWVJM6FcMs5p6xqvZ
ltizeKAjr1B1h4DvbQaqdO6/OAb+dGr7fJoIHEszDsJbW1cc0lUBitrxKHrPGovF
1uEW+3glA3SopveWB4GkKzcYlbqT5y1p/gQNwY8yuZr/6iF1hyF9mx/hU/+xjOMB
og3sGX4npcQegsAMw2y+zz9kJ9a6jlteNufi
=d2Fq
-----END PGP MESSAGE-----
I know that I need to get the random one-time key, that PGP used to encrypt the file, from the data in the file. I know that to do that, I need to use SecKeyDecrypt with the private key, to obtain the one-time AES key. Once I have that key, I can then decrypt the rest of the data.
The part I'm having problems with is which part of the data to feed into SecKeyDecrypt. How is the PGP file setup - is the first 128 chars the AES key? Unless my understanding is wrong, I need to get that out separately from the data.
If I run, say, the first 128 chars as a void through the SecKeyDecrypt function: (after stripping the BEGIN PGP MESSAGE lines)
size_t dataLength = [theKey length];
size_t outputLength = MAX(128, SecKeyGetBlockSize(privateKeyRef));
void *outputBuf = malloc(outputLength);
OSStatus err;
err = SecKeyDecrypt(privateKeyRef, kSecPaddingNone,//PKCS1,
(uint8_t *)theKey, dataLength,
outputBuf, &outputLength);
if (err) {
NSLog(#"something went wrong...err = %ld", err);
}
I get this:
MRªh6∞bJ˘e£t*˝ã=ŒA¢Òt‘ŸY±éÿAÃîâG
Îfi≠$b≈tâç`yxk=uHªqu-,–dïn^™È\›5±tb.‡€Kñ⁄≤sΩw–ïʃkafS˘À*Æô竡rAyv)fi]wOrµKz^ªq“à∑öΓı*r<+l˝Äo∑›g≠¶/÷eÔ&€PÒRåêM¶Ñ|Q$á6În^võ¬∏·h(ƒß•R≤(flò(*•Aa
I don't know what encoding this is, but trying to get it from the outputBuf into a string never works 100%. It seems to get modified no matter what encoding I pass it. If I pass it to NSData first, I can get the original string back.
NSData *keyData = [NSData dataWithBytesNoCopy:outputBuf length:outputLength];
NSString *keyFromData = [[NSString alloc] initWithBytes:[keyData bytes] length:[keyData length] encoding:NSASCIIStringEncoding];
I then try to pass that key to an AES256DecryptWithKey class, providing it with the remaining data from the PGP file, after the first 128 chars.
NSData *cipherText = [[NSData alloc]initWithData:[[bodyPart objectAtIndex:1] dataUsingEncoding:NSUTF8StringEncoding]];
NSData *plain = [[NSData alloc] initWithData:[cipherText AES256DecryptWithKey:keyFromData]];
NSLog(#"after decrypting = %#", [[NSString alloc] initWithData:plain encoding:NSUTF8StringEncoding]);
Problem:
The resulting data 'plain' prints as <> i.e. empty. My problem is I don't even think I know how to grab the key from the PGP file.
Can anyone explain to me the PGP file setup? What part is the 'key' if it is in fact separate from the data at all? Is it always the same length/ same position? If it's NOT separate then I don't know how I'd be able to grab it at all. I think the rest would work fine. I'm not getting any errors or crashes, it's just NOT the right key and/or data I'm passing for AES decryption, I suspect probably a combination of string encoding error and not grabbing the right amount for the AES key/ right combination.
Note -
I created 3 different text files and ran them through the PGP process. Inspecting them, they all started with the same 24 characters (qANQR1DBwEwDraQm2Kxa5GkB). Even if I pass these 24 through the decryption, it doesn't work, and I was under the impression that the AES key PGP used was different for every single document. Did I get that wrong?
Thanks for any step in the right direction!
Edited to add:
Just noticed partly my mistake - AES of 128 requires 16 bits, so either way I am taking the wrong amount by using 128 characters, stupid mistake, think I've been looking at this too long... Swapped it out and didn't work. Any decryption I do is resulting in the '⁄Ĉ¢ï¡0M¶È2Cˆ¿©gUú¨6iîΩ`&<%Jœv£¯nRb∆:(–%' type result, which to me implies I've done something wrong OR need to do something further with encoding.
Read RFC 4880. That file is an ASCII-Armored collection of PGP packets. There are 1 or more packets that contain the symmetric key needed to decrypt the actual message, each of the symmetric key packets is encrypted with the public key of a recipient. Only people who possess the right private key can decrypt the symmetric key packet and then use that symmetric key to decrypt the rest of the message.
The AES key is indeed different.
It is randomly selected, and the encrypted with the public key system (RSA, typically).
Pub key has costs and limitations that make it unattractive to use for bulk.
You might want to look at the NetPGP, which is C code under the
BSD license, which means you can incorporate it or modify it
without encumbering your app or upsetting Apple in any way.
(Of course, contributions of source code or money would be
appreciated by the project. I'm not affiliated with them.)
The OpenPGP standard is a lot of work to implement.
Even once an implementation works, there are countless
ways in which it can be insecure.

Resources