AES256 Decryption with base64 decoding not working - iphone

I need to perform AES 256 decryption in my iphone app. The scenario is that the plain text is base64 encoded and encrypted using AES256 bit (OFB mode) in an online webpage.
In my app, I retrieve the encrypted text from that webpage as a query string. Here I have done base64 decoding and AES256 Decryption.
But I am getting -4304 status.
I have used kCCOptionPKCS7Padding. Even if I change the padding also, I am not getting proper Decrypted Plain text. Only unreadable text is displayed.
I have used http://isv.appspot.com/app/enc for checking the AES256 encryption with base64 by setting OFB mode.
Following code has two methods which I used for base64 decoding and AES256 decryption
+ (NSString*)decryptBase64String:(NSString*)encryptedBase64String keyString:(NSString*)keyString
{
NSData* encryptedData = [NSData dataFromBase64String:encryptedBase64String];
NSLog(#"encryptedData %#",encryptedData);
// NSData *strData = [encryptedData subdataWithRange:NSMakeRange(0, [encryptedData length] - 2)];
// NSString* newStr = nil;
NSData* keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
NSData* data = [self decryptData:encryptedData
key:keyData
iv:nil];
// newStr = [NSString stringWithCString:[strData bytes] encoding:NSUTF8StringEncoding];
if (data) {
return [[[NSString alloc] initWithData:data
encoding:NSASCIIStringEncoding] autorelease];
} else {
return nil;
}
}
+ (NSData*)decryptData:(NSData*)data key:(NSData*)key iv:(NSData*)iv;
{
NSData* result = nil;
// setup key
unsigned char cKey[FBENCRYPT_KEY_SIZE];
bzero(cKey, sizeof(cKey));
[key getBytes:cKey length:FBENCRYPT_KEY_SIZE];
// setup iv
char cIv[FBENCRYPT_BLOCK_SIZE];
bzero(cIv, FBENCRYPT_BLOCK_SIZE);
if (iv) {
[iv getBytes:cIv length:FBENCRYPT_BLOCK_SIZE];
}
// setup output buffer
size_t bufferSize = [data length] + FBENCRYPT_BLOCK_SIZE;
void *buffer = malloc(bufferSize);
// do decrypt
size_t decryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
FBENCRYPT_ALGORITHM,
kCCOptionPKCS7Padding,
cKey,
FBENCRYPT_KEY_SIZE,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&decryptedSize);
if (cryptStatus == kCCSuccess) {
result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
} else {
free(buffer);
NSLog(#"[ERROR] failed to decrypt| CCCryptoStatus: %d", cryptStatus);
}
return result;
}
Could anyone help me out to get the plain text by using this method?

Based on the facts in your question, the base64 encoded data is encrypted, not the decoded variation of that data. Because of this, you need to decrypt the base64 encoded data and then base64 decode it.

Related

AES 256/CBC/Withoutpadding in objective-c

I'm trying to achieve AES 256 with zero padding and CBC mode . I tried all methods from cypto but results are coming different what is from the server
I'm using this code
Where I'm passing simple string for check in databstring , key and iv is passed as "iphone".
/**************
- (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;
CCCryptorRef cryptorRef;
CCCryptorStatus rc;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, 0,
keyData.bytes, kCCKeySizeAES256,
ivData.bytes, // initialisation vector
dataToEncrypt.bytes,
dataToEncrypt.length, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
// NSString *someDataHexadecimalString = [[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted] hexadecimalString];
NSLog(#"%#",[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]);
//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;
}
**********/
But it prints different result everytime.
please help.
Your IV ("iphone") is too short. CBC mode requires an IV equal to the block size of the cipher algorithm (16 bytes for AES). CCCrypt reads 16 bytes from your provided iv buffer, and since yours is too short, whatever garbage happens to be in memory after the end of the buffer will be used as the rest of the IV.
So essentially you are using a different IV each time, which is why your ciphertext is different each time.
In general, don't use strings for IVs. For security, the IV should be different for each different message, and that's hard to do if you are using hard-coded strings. Just generate 16 random bytes for the IV, and put them at the beginning of the cipher text.

RSA decryption with openSSL

I have a problem with RSA encrypted and Base 64 encoded text decryption. When i decrypt directly encrypted text(unsigned char *) then everything is okay and I get correct result. But when I do base64 encoding, than openssl fails to decrypt data, although base64 decoded data is exactly same as was encrypted data:
For example(first is encryption result and second base 64 decoding result. Decoding first char * directly works pretty well.)
encrypted - ßÁ¨£®Òz>Ô‹n.€Ö∫BÔ–∂ü∏ÕD⁄UÖáµ)ûKufi wÆ&_è”eëõ~gK∂¶$kŸƒ∫ª`ÔfΩ˙˛{∆_MªÔëbP Q¶fl±Ü;!ü•◊s>ħ∆◊⁄≤ò˙ˇCWôVÂzôzíö≤ÙU¶?⁄l[*H?o\ñ>ƒ<‘4mœ“Lr
Íhh
decoded string - ßÁ¨£®Òz>Ô‹n.€Ö∫BÔ–∂ü∏ÕD⁄UÖáµ)ûKufi wÆ&_è”eëõ~gK∂¶$kŸƒ∫ª`ÔfΩ˙˛{∆_MªÔëbP Q¶fl±Ü;!ü•◊s>ħ∆◊⁄≤ò˙ˇCWôVÂzôzíö≤ÙU¶?⁄l[*H?o\ñ>ƒ<‘4mœ“Lr
Íhh
Code:
+(NSString *) rsaEncryptedStringFromText: (NSString *) text
{
const char *message = [text UTF8String];
NSLog(#"message - %s", message);
int bufSize;
NSString *keyFilePath = [[NSBundle mainBundle] pathForResource:#"publicKey" ofType:#"pem"];
FILE *keyfile = fopen([keyFilePath UTF8String], "r");
RSA *rsa = PEM_read_RSA_PUBKEY(keyfile, NULL, NULL, NULL);
if (rsa == NULL)
{
return nil;
}
int key_size = RSA_size(rsa);
unsigned char *encrypted = (unsigned char *) malloc(key_size);
bufSize = RSA_public_encrypt(strlen(message), (unsigned char *) message, encrypted, rsa, RSA_PKCS1_PADDING);
if (bufSize == -1)
{
RSA_free(rsa);
return nil;
}
NSLog(#"encrypted - %s", encrypted);
NSData *encryptedData = [NSData dataWithBytes:encrypted length:strlen((const char *)encrypted)];
NSString *base64 = [encryptedData base64Encoding];
RSA_free(rsa);
return base64;
}
+(NSString *) rsaDecryptToStringFromText: (NSString *) text
{
//NSLog(#"text - %#", text);
NSData *decodedData = [NSData dataWithBase64EncodedString: text];
unsigned char* message = (unsigned char*) [decodedData bytes];
NSLog(#"decoded string - %s", message);
RSA *privKey = NULL;
FILE *priv_key_file;
unsigned char *ptext;
NSString *keyFilePath = [[NSBundle mainBundle] pathForResource:#"privateKeyPair" ofType:#"pem"];
priv_key_file = fopen([keyFilePath UTF8String], "rb");
ERR_print_errors_fp(priv_key_file);
privKey = PEM_read_RSAPrivateKey(priv_key_file, NULL, NULL, NULL);
int key_size = RSA_size(privKey);
ptext = malloc(key_size);
int outlen = RSA_private_decrypt(key_size, (const unsigned char*)message, ptext, privKey, RSA_PKCS1_PADDING);
if(outlen < 0) return nil;
RSA_free(privKey);
return [NSString stringWithUTF8String: (const char *)ptext];
}
Base 64 encoding-decoding is done with this:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/21689-base-64-string-help.html#post98080
Main problem was in base64 encoding+decoding class. Switched to QSutilities and everything works.

Objective-C decrypt AES 128 cbc hex string

I am developing an application for iPhone on Snow Leopard with Xcode 3.1 that receives from a restful web service an encrypted text in hexadecimal format with the algorithm AES 128-bit (CBC). The algorithm uses an initialization vector + secret key. How do I decrypt this text? Thanks to everyone for the tips that I will succeed in giving.
EDIT:
I get response from REST Server in hex AND crypted format,I try with this code but i receive always bad param error. Can you help me to find the error?
Is it possible that i firstly convert the string response into binary format?
NSString *response = [request responseString];
NSData *encryptedData = [response dataUsingEncoding: NSASCIIStringEncoding];
NSString *key = #"32charlength";
NSString *iv = #"16charlength";
NSData *unencryptedData = NULL;
size_t unencryptedLength = [unencryptedData length];
CCCryptorStatus ccStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0, key, kCCKeySizeAES128, iv, [encryptedData bytes], [encryptedData length], unencryptedData, [encryptedData length], &unencryptedLength);
NSString *output = [[NSString alloc] initWithBytes:unencryptedData length:unencryptedLength encoding:NSUTF8StringEncoding];
if (ccStatus == kCCSuccess) risultato.text = #"SUCCESS";
else if (ccStatus == kCCParamError) risultato.text = #"BAD PARAM";
else if (ccStatus == kCCBufferTooSmall) risultato.text = #"BUFFER TOO SMALL";
else if (ccStatus == kCCMemoryFailure) risultato.text = #"MEMORY FAILURE";
else if (ccStatus == kCCAlignmentError) risultato.text = #"ALIGNMENT";
else if (ccStatus == kCCDecodeError) risultato.text = #"DECODE ERROR";
else if (ccStatus == kCCUnimplemented) risultato.text = #"UNIMPLEMENTED";
EDIT2:
this function return BAD PARAM because haven't the right buffer size where allocate decrypted data. I edit the function in this working way:
NSData *encryptedData = [response dataUsingEncoding: NSASCIIStringEncoding];
const void *key = #"32charlength;
uint8_t *iv = #"16charlength";
char buffer[4*4096];
memset(buffer, '\0', sizeof(buffer));
size_t size = sizeof(buffer);
CCCryptorStatus ccStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
0,
key,
kCCKeySizeAES128,
iv,
[encryptedData bytes],
[encryptedData length],
buffer,
sizeof(buffer),
&size);
This function working for me.. thanks so much.
EDIT 23 MARCH------
Now the system work form me with 16 byte key size. Now i have a question, what i can do to implement 32 byte key size ? thanks so much.
This is possible using the CCCryptor functions included in the <CommonCrypto/CommonCryptor.h> header. Check man CCCryptor for the gory details, in your case it sounds like you can use a single call to CCCrypt() to decode the received data:
CCCryptorStatus
CCCrypt(CCOperation op, CCAlgorithm alg, CCOptions options, const void *key, size_t keyLength,
const void *iv, const void *dataIn, size_t dataInLength, void *dataOut, size_t dataOutAvailable,
size_t *dataOutMoved);
Assuming you have the data to be decrypted in NSData *encryptedData you could try something like:
char * key = "shouldbe16chars.";
NSUInteger dataLength = [encryptedData length];
uint8_t unencryptedData[dataLength + kCCKeySizeAES128];
size_t unencryptedLength;
CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0, key, kCCKeySizeAES128, NULL, [encryptedData bytes], dataLength, unencryptedData, dataLength, &unencryptedLength);
NSString *output = [[NSString alloc] initWithBytes:unencryptedData length:unencryptedLength encoding:NSUTF8StringEncoding];
This is untested, make sure you check the return value of CCCrypt for errors. Check the header file for details, it is well documented.

AES Encryption using IV, Salt, RFC2898 iteration, Key Generation using SHA1 algorithm in iPhone

I have a problem related to AES Encryption. The problem is I need to encrypt the string using AES encryption technique with Intialization Vector, Salt, RFC2898 iteration and Generate a key using sha1 algorithm.
I used this code
+(NSString *)stringToSha1:(NSString *)str{
const char *s = [str cStringUsingEncoding:NSASCIIStringEncoding];
NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];
// This is the destination
uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};
// This one function does an unkeyed SHA1 hash of your hash data
CC_SHA1(keyData.bytes, keyData.length, digest);
// Now convert to NSData structure to make it usable again
NSData *out = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
// description converts to hex but puts <> around it and spaces every 4 bytes
NSString *hash = [out description];
hash = [hash stringByReplacingOccurrencesOfString:#" " withString:#""];
hash = [hash stringByReplacingOccurrencesOfString:#"<" withString:#""];
hash = [hash stringByReplacingOccurrencesOfString:#">" withString:#""];
NSLog(#"Hash is %# for string %#", hash, str);
return hash;
}
For sha1 key generation but it produces totally different as this technique do in .net and Android.
Android and .net already have classes and library to do this and i left alone so how I can do it in iPhone.
This should be what you need
+ (NSData *)sha1HashFromString:(NSString *)stringToHash {
NSData *stringData = [stringToHash dataUsingEncoding:NSASCIIStringEncoding];
uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};
CC_SHA1([stringData bytes], [stringData length], digest);
NSData *hashedData = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
return [hashedData autorelease];
}

AES Encryption for an NSString on the iPhone

Can anybody point me in the right direction to be able to encrypt a string, returning another string with the encrypted data? (I've been trying with AES256 encryption.) I want to write a method which takes two NSString instances, one being the message to encrypt and the other being a 'passcode' to encrypt it with - I suspect I'd have to generate the encryption key with the passcode, in a way that can be reversed if the passcode is supplied with the encrypted data. The method should then return an NSString created from the encrypted data.
I've tried the technique detailed in the first comment on this post, but I've had no luck so far. Apple's CryptoExercise certainly has something, but I can't make sense of it... I've seen lots of references to CCCrypt, but it's failed in every case I've used it.
I would also have to be able to decrypt an encrypted string, but I hope that's as simple as kCCEncrypt/kCCDecrypt.
Since you haven't posted any code, it's difficult to know exactly which problems you're encountering. However, the blog post you link to does seem to work pretty decently... aside from the extra comma in each call to CCCrypt() which caused compile errors.
A later comment on that post includes this adapted code, which works for me, and seems a bit more straightforward. If you include their code for the NSData category, you can write something like this: (Note: The printf() calls are only for demonstrating the state of the data at various points — in a real application, it wouldn't make sense to print such values.)
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *key = #"my password";
NSString *secret = #"text to encrypt";
NSData *plain = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *cipher = [plain AES256EncryptWithKey:key];
printf("%s\n", [[cipher description] UTF8String]);
plain = [cipher AES256DecryptWithKey:key];
printf("%s\n", [[plain description] UTF8String]);
printf("%s\n", [[[NSString alloc] initWithData:plain encoding:NSUTF8StringEncoding] UTF8String]);
[pool drain];
return 0;
}
Given this code, and the fact that encrypted data will not always translate nicely into an NSString, it may be more convenient to write two methods that wrap the functionality you need, in forward and reverse...
- (NSData*) encryptString:(NSString*)plaintext withKey:(NSString*)key {
return [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
}
- (NSString*) decryptData:(NSData*)ciphertext withKey:(NSString*)key {
return [[[NSString alloc] initWithData:[ciphertext AES256DecryptWithKey:key]
encoding:NSUTF8StringEncoding] autorelease];
}
This definitely works on Snow Leopard, and #Boz reports that CommonCrypto is part of the Core OS on the iPhone. Both 10.4 and 10.5 have /usr/include/CommonCrypto, although 10.5 has a man page for CCCryptor.3cc and 10.4 doesn't, so YMMV.
EDIT: See this follow-up question on using Base64 encoding for representing encrypted data bytes as a string (if desired) using safe, lossless conversions.
I have put together a collection of categories for NSData and NSString which uses solutions found on Jeff LaMarche's blog and some hints by Quinn Taylor here on Stack Overflow.
It uses categories to extend NSData to provide AES256 encryption and also offers an extension of NSString to BASE64-encode encrypted data safely to strings.
Here's an example to show the usage for encrypting strings:
NSString *plainString = #"This string will be encrypted";
NSString *key = #"YourEncryptionKey"; // should be provided by a user
NSLog( #"Original String: %#", plainString );
NSString *encryptedString = [plainString AES256EncryptWithKey:key];
NSLog( #"Encrypted String: %#", encryptedString );
NSLog( #"Decrypted String: %#", [encryptedString AES256DecryptWithKey:key] );
Get the full source code here:
https://gist.github.com/838614
Thanks for all the helpful hints!
-- Michael
#owlstead, regarding your request for "a cryptographically secure variant of one of the given answers," please see RNCryptor. It was designed to do exactly what you're requesting (and was built in response to the problems with the code listed here).
RNCryptor uses PBKDF2 with salt, provides a random IV, and attaches HMAC (also generated from PBKDF2 with its own salt. It support synchronous and asynchronous operation.
I waited a bit on #QuinnTaylor to update his answer, but since he didn't, here's the answer a bit more clearly and in a way that it will load on XCode7 (and perhaps greater). I used this in a Cocoa application, but it likely will work okay with an iOS application as well. Has no ARC errors.
Paste before any #implementation section in your AppDelegate.m or AppDelegate.mm file.
#import <CommonCrypto/CommonCryptor.h>
#implementation NSData (AES256)
- (NSData *)AES256EncryptWithKey:(NSString *)key {
// '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];
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;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* 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;
}
- (NSData *)AES256DecryptWithKey:(NSString *)key {
// '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];
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 numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer); //free the buffer;
return nil;
}
#end
Paste these two functions in the #implementation class you desire. In my case, I chose #implementation AppDelegate in my AppDelegate.mm or AppDelegate.m file.
- (NSString *) encryptString:(NSString*)plaintext withKey:(NSString*)key {
NSData *data = [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
return [data base64EncodedStringWithOptions:kNilOptions];
}
- (NSString *) decryptString:(NSString *)ciphertext withKey:(NSString*)key {
NSData *data = [[NSData alloc] initWithBase64EncodedString:ciphertext options:kNilOptions];
return [[NSString alloc] initWithData:[data AES256DecryptWithKey:key] encoding:NSUTF8StringEncoding];
}
Please use the below mentioned URL to encrypt string using AES excryption with
key and IV values.
https://github.com/muneebahmad/AESiOSObjC