iPhone encrypt function that would be decrypt on php server - iphone

I want to write encrypt function in iPhone application that would be decrypt on server in php,
Decrypt function in php is this
function decrypt($input_text)
{
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$enc_key = "0e9d083f3514a69243bb8f1395d332c1";
$out = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $enc_key, $input_text, MCRYPT_MODE_ECB, $iv);
return $out;
}
I'm using following encryption code in iPhone
+(NSString*) encrypt:(NSString*) str key:(NSString*) key
{
NSString *key =key;
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero( keyPtr, sizeof(keyPtr) ); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char *dataIn = [str UTF8String];
char dataOut[500];// set it acc ur data
bzero(dataOut, sizeof(dataOut));
size_t numBytesEncrypted = 0;
CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,kCCOptionPKCS7Padding|kCCOptionECBMode, keyPtr,kCCKeySizeAES128, NULL, dataIn, strlen(dataIn), dataOut, sizeof(dataOut), &numBytesEncrypted);
NSString* strResult = [[[NSString alloc] initWithCString:dataOut] autorelease];
return [strResult copy];
}
but didn't get the original result.
Please anybody can correct me where i'm wrong

Try:
As said, use the same key length in both cases.
In the CCCrypt call you don't store the iv that was generated, instead you pass NULL. You should store this and somehow transport it along the message to your PHP code. There, instead of generating a new, random iv you would reuse the existing one generated by the iPhone.
On top of that, mcrypt does not support PKCS7Padding (also often referred to as PKCS5Padding), so unfortunately you need to implement it yourself. In your case, you first decrypt the iPhone's input and then apply the pkcs5_unpad function described in that article afterwards.

You are using AES with 256-bit key in the decryption and with 128-bit key in the encryption. These are entirely different algorithms.

Related

AES-256 encryption on iOS not producing same result as openssl

I have been looking and looking at this for hours. I am desperately trying to get iOS to encrypt a short piece of text using AES-256 encryption that can then be decrypted by openssl.
Straight forward? Nope.
The code I've found for iOS is not compatible with the keys and IVs for openssl, so I've had to adapt it, but it's plainly not working.
So here is the code to encrypt I am using... passing in a string to encrypt (dataString) a string key (key) and a string initialisation vector (iv)...
- (NSData *)AES256Encrypt:(NSString *)dataString WithKey:(NSString *)key iv:(NSString *)iv {
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
//char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
//bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
//[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
//NSLog(#"keyPtr: '%s'", keyPtr);
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"keyPtr: '%s'", keyData.bytes);
NSData *dataToEncrypt = [dataString dataUsingEncoding:NSUTF8StringEncoding];
NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger dataLength = [dataToEncrypt length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyData.bytes, kCCKeySizeAES256,
ivData.bytes, // initialisation vector
dataToEncrypt.bytes,
dataToEncrypt.length, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
For the same string to encode, this does not produce the same value as when using openssl with the same key and iv... e.g. this command line:
openssl enc -aes-256-cbc -e -in secrets.txt -a -iv 0000 -K 0000 -p
secrets.txt is just a text file containing the string to be encrypted
This outputs something like this:
salt=3C66000000000000
key=0000000000000000000000000000000000000000000000000000000000000000
iv =00000000000000000000000000000000
qTMfgtAxbF8Yyh27ZDrcIQ==
And to decrypt, do the opposite operation (assuming the encrypted last line of data above is in test.secrets.out)
openssl enc -aes-256-cbc -d -in test.secrets.out -a -iv 0000 -K 0000 -p
salt=3C66000000000000
key=0000000000000000000000000000000000000000000000000000000000000000
iv =00000000000000000000000000000000
< text of the secrets.txt file >
Now, if I use the key and iv of 4 chars, this doesn't encode correctly in iOS. If I use the full length key and iv, this doesn't encode correctly either.
Basically, this is a check to see that if I send a piece of encrypted data it is the right piece of data.
What am I missing?
Some code I've looked through to try to find an answer...
http://robnapier.net/blog/aes-commoncrypto-564
https://github.com/rnapier/RNCryptor
http://pastie.org/426530
Have searched extensively on here too and cannot find an answer.
Any help appreciated.
OpenSSL has a unique (read "not close to any standard, and also not particularly secure") method for converting passwords into IV and key. If you look at RNOpenSSLCryptor, you'll see the algorithm used:
// For aes-128:
//
// key = MD5(password + salt)
// IV = MD5(Key + password + salt)
//
// For aes-256:
//
// Hash0 = ''
// Hash1 = MD5(Hash0 + Password + Salt)
// Hash2 = MD5(Hash1 + Password + Salt)
// Hash3 = MD5(Hash2 + Password + Salt)
// Hash4 = MD5(Hash3 + Password + Salt)
//
// Key = Hash1 + Hash2
// IV = Hash3 + Hash4
//
// File Format:
//
// |Salted___|<salt>|<ciphertext>|
//
Using RNOpenSSLCryptor allows RNCryptor support for the OpenSSL format. I am currently in the midst of reworking this code on the async branch to support async operations, and that branch doesn't yet support OpenSSL, but I do plan to rework that shortly (by mid-July 2012).
If you want code that implements this for your own use, look at keyForPassword:salt: and IVForKey:password:salt:.
Note that the the OpenSSL file format has several security problems and I don't recommend it if you can avoid it. It does not use a very good KDF to generate its key, does not have as random an IV as it should, and provides no HMAC for authentication. These security problems are why I designed a different file format, much as I hated creating "yet another incompatible container."

NSXMLparse to pull specific values from a long string.(Couple Questions.)

Excuse me if this is a question that has been asked before, if so point me to the right answer.(i couldn't find the answer.)
My Question's:
I have an XML coming in from a NSUrl i need to be able to parse it appropriately,
i will be receiving the responses with Field Perpetrators in them such as ().
Could i have it set up to search a dictionary for Keywords and parse them from the XML?
If so what would be a good start on learning that?
Also is it possible to save the response's and encrypt them until i need to use them in another view?
if so, what is the best way to encrypt on the IOS side?
any guide in the right direction is wonderful!!
I'm not asking for someone to answer all of them but it would be nice, thank you!
The method - (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)mask error:(NSError **)errorPtr
has NSDataWritingFileProtection options that will encrypt the data for you but you have no control over they encryption key.
For encryption use CommonCrypro (part of iOS), aes128, cbc. But the real question is how will you securely save the encryption key?
Here is an encryption/decryption method:
+ (NSData *)doCipher:(NSData *)dataIn
iv:(NSData *)iv
key:(NSData *)symmetricKey
context:(CCOperation)encryptOrDecrypt
{
CCCryptorStatus ccStatus = kCCSuccess;
size_t cryptBytes = 0; // Number of bytes moved to buffer.
NSMutableData *dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];
ccStatus = CCCrypt( encryptOrDecrypt, // kCCEncrypt or kCCDecrypt
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
symmetricKey.bytes,
kCCKeySizeAES128,
iv.bytes,
dataIn.bytes,
dataIn.length,
dataOut.mutableBytes,
dataOut.length,
&cryptBytes);
if (ccStatus != kCCSuccess) {
NSLog(#"CCCrypt status: %d", ccStatus);
}
dataOut.length = cryptBytes;
return dataOut;
}

Encrypt with openssl and decrypt on iPhone with AES 128, ecb mode

Update : found the solution. I will update this question soon with the actual working code and command.
A client is encrypting a file server-side with C++, and I need to decrypt it in an iPhone application.
My client can crypt and decrypt on his side, and so do I on the iPhone, but we can't decrypt the file encrypted by each other.
I saw many related questions on SO, but none could help me find an implementation that works the same way on both side.
I want to output some sample values that we will accept as the common implementation.
I tried to crypt a file with openssl and decrypt it with cocoa, but couldn't.
Here is what I use for encryption:
echo "123456789ABCDEFG" | openssl enc -aes-128-ecb -nosalt -K "41414141414141414141414141414141" -iv 0 > hello.txt.bin
Adding the option -p to openssl call shows that the expected key and iv are used:
key=41414141414141414141414141414141
iv =00000000000000000000000000000000
And for cocoa decryption (in an NSData category):
- (NSData *)AESDecryptWithKey:(NSString *)key {
char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
char iv[32];
for (int i = 0; i < 32; i++) {
iv[i] = 0;
}
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode + kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
iv, //"00000000000000000000000000000000" /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
called this way:
- (void)testBinaryFileDecryption {
NSString *databasePath = [[NSBundle mainBundle] pathForResource:#"hello" ofType:#"txt.bin"];
NSData *data = [NSData dataWithContentsOfFile:databasePath];
NSAssert(nil != data, #"Encrypted data, freshly loaded from file should not be nil");
NSData *plain = [data AESDecryptWithKey:#"AAAAAAAAAAAAAAAA"];
NSAssert(nil != plain, #"Decrypted plain data should not be nil");
NSLog(#"Result: '%#'", [[NSString alloc] initWithData:plain encoding:NSASCIIStringEncoding]);
}
Result logs:
Result: '4¨µ¢Ä½Pk£N
What option am I forgetting? Is the encoding of the NSData returned something else than NSASCIIStringEncoding ?
I know nothing of iPhone development, but looking at this code, it appears you're trying to use the ascii-of-hex-encoding of the actual key to decrypt the packet. OpenSSL's enc requires the hex encoding because it converts the hex into bytes. Your actual key looks more like this, when converted directly to ascii.
["\037", " ", "!", "\"", "#", "$", "%", "&", "'", "\036", "\037", " ", "!", "\"", "#", "$"]
(All that might be obtuse. If you were to encode the string you're using for decrypting into the same format that OpenSSL enc accepts, the key would be 3331333233333334333533363337333833393330333133323333333433353336.)
Try using a key specification of 41414141414141414141414141414141 to OpenSSL and use AAAAAAAAAAAAAAAA in your iPhone code.
Also, I strongly suggest your initial tests be made with data that is exactly N*16 bytes long. OpenSSL enc uses PKCS#5 padding (unless you use -nopad), and your iPhone code is using PKCS#7 padding. On a cursory glance at RFCs, they seem to be the same padding mechanism, but I could be wrong.
And I know you're just trying things out here, but in real production code, please do not use ECB mode.
I'm using Crypt::OpenSSL::AES to encrypt files that are decrypted in my iOS app, which decrypts using CommonCryptor.
cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0,
keyPtr, kCCKeySizeAES256,
IVECTOR /* initialization vector (optional) -- was NULL*/,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted);
To initialize the IVECTOR I'm using bzero.
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
To encrypt under OpenSSL in perl I do this:
my $cipher = Crypt::CBC->new( -key => $key,
-literal_key => 1,
-header => 'none',
-iv => '0000000000000000',
-cipher => 'Crypt::OpenSSL::AES' );
OpenSSL seems to accept the '0000000000000000' IV as the same thing as ASCII 0 (null) characters. Seems plausible in retrospect, but it required a lot of hair pulling because every crypto failure looks like every other crypto failure: garbage out.

Encrypting streaming content onto persistent storage and decrypting it to the stream on iPhone

My app "streams" content (fixed sized files, hence quotation marks) from an HTTP server into a local file. Then there is another component of the app that opens that same file and displays it (plays it).
This is done for caching purposes, so that when the same file is requested next time, it will no longer need to be downloaded from the server.
App's spec requires that all local content is encrypted (even with the most light weight encryption)
Question: has there been done any work, allowing one to simply redirect the stream to a library which will then save the stream encrypted into a file? And then, when I request the stream from the local file, the library returns an on the fly decrypted stream?
I've been searching for a solution with no results so far
Thanks
I ended up writing a custom solution that uses RC4 encryption from the built in Crypt library. It was surprisingly straight forward. Basically it involved creating a function that encrypts/decrypts chunks of NSData and then read/write those chunks to files... Here's the function that does the encryption in case someone else is interested:
- (NSData*)RC4EncryptDecryptWithKey:(NSString *)key operation:(CCOperation)operation
{
// convert to C string..
int keySize = [key length];
char keyPtr[keySize];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr
maxLength:sizeof(keyPtr)
encoding:NSUTF8StringEncoding];
// encode/decode
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength;
void *buffer = malloc(bufferSize);
size_t numBytesOut = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmRC4,
kCCOptionECBMode,
keyPtr,
8,
NULL,
[self bytes],
dataLength,
buffer,
bufferSize,
&numBytesOut);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer
length:numBytesOut
freeWhenDone:YES];
}
free(buffer);
return nil;
}
- (NSData*)RC4EncryptWithKey:(NSString*)key {
return [self RC4EncryptDecryptWithKey:key operation:kCCEncrypt];
}
- (NSData*)RC4DecryptWithKey:(NSString*)key {
return [self RC4EncryptDecryptWithKey:key operation:kCCDecrypt];
}
Obviously one could create something more secure (eg AES) or whatever (in fact I used examples of other encryption wrappers to write this one)
I wouldn't worry about encryption just because Apple says so.
Make this work how you want it (without encryption, it sounds like) and submit it for approval. If approved, you're good. If not, worry about it then. If your design requires you to make a decision now, your design might be flawed.

encrypt data on iphone and dencrypt on a .net web application

I was to encrypt data on the device and send it by http to our web server then decrypt the data on out .net web app. Is this possible? If yes, which encryption method I should use? and if their are any articles out there?
Thanks
SSL should be the standard solution for HTTP encryption. NSURLConnection supports it out of the box (just load an https:// request), so you would just have to set up your server accordingly.
As you don't want to use SSL (and I agree there are many good reasons not to do so) you can use the built in CommonCrypto framework to encrypt just the data you need to. Here is a simple NSData category to encrypt arbitrary data:
#implementation NSData (AES256)
- (NSData*) encryptedWithKey: (NSString *) key;
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyBuffer[kCCKeySizeAES128+1]; // room for terminator (unused)
bzero( keyBuffer, sizeof(keyBuffer) ); // fill with zeroes (for padding)
[key getCString: keyBuffer maxLength: sizeof(keyBuffer) encoding: NSUTF8StringEncoding];
// encrypts in-place, since this is a mutable data object
size_t numBytesEncrypted = 0;
size_t returnLength = ([self length] + kCCKeySizeAES256) & ~(kCCKeySizeAES256 - 1);
// NSMutableData* returnBuffer = [NSMutableData dataWithLength:returnLength];
char* returnBuffer = malloc(returnLength * sizeof(uint8_t) );
CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmAES128 , kCCOptionPKCS7Padding | kCCOptionECBMode,
keyBuffer, kCCKeySizeAES128, nil,
[self bytes], [self length],
returnBuffer, returnLength,
&numBytesEncrypted);
if(result == kCCSuccess)
return [NSData dataWithBytes:returnBuffer length:numBytesEncrypted];
else
return nil;
}
#end
Note that this also turns on ECB Mode which you may not want. Also remember that the data that comes back from this call is not suitable for use in URLs you will have to base 64 encode it.
If SSL is not an option use AES encryption in CBC mode. 128 encryption bit is all you need and you can use anything (0 is acceptable) as the IV.