implementing password hashing in iOS applications - ios

I am trying to implement password hashing in my iPad application.I found secure salted password hashing link which is having sample codes of java, .net ,etc but not ios. Can anybody help me to found a solution in the same way how they are doing...

Use common crypto library for making md5 of your password.
#import <CommonCrypto/CommonDigest.h>
and then use.
- (NSString *) md5:(NSString *) input
{
const char *cStr = [input UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return output;
}

Note that MD5 is insecure and shouldn't be used for hashing sensitive information such as passwords. You should instead use SHA1 or SHA256 like this:
+ (NSData *)sha256:(NSData *)data {
unsigned char hash[CC_SHA256_DIGEST_LENGTH];
if(CC_SHA256([data bytes], [data length], hash) ) {
NSData *sha256 = [NSData dataWithBytes:hash length: CC_SHA256_DIGEST_LENGTH];
return sha256;
}
return nil;
}

Related

iOS Youku play video with password failed

I try to play youku video with YKMediaPlayerSDK on iOS app. Passing password as parameter will show the password is wrong. This video and password works fine in our android version app.
Thanks for helping.
NSString *passwordAndClientID = [NSString stringWithFormat:#"%#%#", _youkuPW, _VideoId];
NSLog(#"clientIDAndPassword: %#", passwordAndClientID);
NSString *md5 = [self md5:passwordAndClientID];
NSLog(#"md5: %#", md5);
[_cloudPlayer playVid:_VideoId quality:_itemQuality language:#"default" password:passwordAndClientID from:0];
MD5 method
- (NSString *) md5:(NSString *) input {
const char *cStr = [input UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5( cStr, (CC_LONG)strlen(cStr), digest ); // This is the md5 call
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return [output copy];
}
It's seems like a bug in there SDK, we turn off password to solve it!

proper way of AES128Encryption for a password in ios

I'm facing a problem of password encryption. I'm using AES128 to encrypt the data. Here is the following code:
LoginController.m
#import <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonKeyDerivation.h>
#import "NSData+AES.h"
- (IBAction)loginButtonClick:(id)sender
{
NSData *toencrypt = [password.text dataUsingEncoding:NSUTF8StringEncoding];
NSString *credentials = [self md5:[NSString stringWithFormat:#"63jhdf83hf73haf3983f"]]; //returns 679fb1ddf7d81bee0aff2ef251fe6bf5
NSString *iv = #"kdf67398DF7383fd";
NSData *data = [toencrypt AES128EncryptWithKey:credentials iv:iv];
NSString *postdata = [data base64Encoding]; //base64Encoding is implemented in NSData+AES.m
NSLog(#"Original Password: %#",password);
NSLog(#"Encrypted Password: %#",postdata);
}
**N.B: md5 conversion and base64Encoding is working fine.
NSData+AES.m
static char encodingTable[64] =
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
};
#implementation NSData (AES)
- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv
{
char keyPtr[kCCKeySizeAES128+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCKeySizeAES128+1];
bzero(ivPtr, sizeof(ivPtr));
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
int newSize = 0;
if(diff > 0){
newSize = (int)dataLength + diff;
}
char dataPtr[newSize];
memcpy(dataPtr, [self bytes], [self length]);
for(int i = 0; i < diff; i++){
dataPtr[i + dataLength] = 0x00;
}
size_t bufferSize = newSize + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
0x00, //No padding
keyPtr,
kCCKeySizeAES128,
ivPtr,
dataPtr,
sizeof(dataPtr),
buffer,
bufferSize,
&numBytesEncrypted);
if(cryptStatus == kCCSuccess)
{
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
return nil;
}
Now If a send "brad" it should return "ur/bq4Rz". But unfortunately it returning "83+eQZW3eI4UWGdNk4nnUw==". Whats the problem? Please help me out. Thanks in advance.
Note that this code is pretty insecure. It reuses the same Key+IV for every message, which greatly simplifies the job of decrypting the message for an attacker (especially short messages). And it has other security problems (poor keyspace, bad padding scheme)
That said, the piece that is specifically broken is that you're passing a 32-byte (256-bit) "key" but you're only using 128-bits of it. You probably meant to use kCCKeySizeAES256 as the key length. This is unrelated to kCCAlgorithmAES128 which refers to the block size, not the key length. In the diff code, you meant to use kCCBlockSizeAES128 rather than kCCKeySizeAES128, but they are both 16 so it doesn't impact the result.
As #Codo notes, standard CBC mode cannot output cipher text that is not a multiple of 16 bytes in length. Why do you believe "ur/bq4Rz" is the correct encryption? There is a modification of CBC that can do this (it adds what is called "cipher text stealing" or CTS), but this isn't supported by iOS.
Your code is doing zero-padding, which is a very poor way to do it (you're just adding zeros until you get to a 16-byte boundary). The standard (and more secure) solution is PKCS#7 padding, which you're turning off.
If I had to guess, you're copying code that zero-pads the data and then truncates the cipher text to length. The decryption then probably pads the cipher text with zeros and then truncates the garbage at the end (probably based on knowing the length beforehand). I see how this can work, but it's not the normal approach.
If you want an example of how to do this simply, see Properly Encrypting With AES and CommonCrypto. If you want a more secure approach that does all of it for you, see RNCryptor. Neither of these will generate cipher text that is the same length as your plaintext, however.
I found some issues, for example you don't check if getCString:maxLength:endocind failed or not. This is deprecated function and it may fail here, as a result encryption method may use completly different key and IV
Here is my version of this method. This should do the job right:
- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv
{
int diff = kCCKeySizeAES128 - (self.length % kCCKeySizeAES128);
NSMutableData *adjustedData = [NSMutableData dataWithData:self];
[adjustedData appendData:[[NSMutableData alloc] initWithLength:diff]];
size_t bufferSize = adjustedData.length + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
0x00, //No padding
[key UTF8String], kCCKeySizeAES128,
[iv UTF8String],
adjustedData.bytes,
adjustedData.length,
buffer,
bufferSize,
&numBytesEncrypted);
if(cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
return nil;
}

How to use CCHmac in iOS?

I want to generate SHA512 with salt in iOS. I found following snippet to achieve this but I found that CCHmac() function is for mac.
-(NSString *)hashString:(NSString *)data withSalt:(NSString *)salt
{
const char *cKey = [salt cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [data cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSString *hash;
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[output appendFormat:#"%02x", cHMAC[i]];
}
hash = output;
return hash;
}
If I use CC_SHA512() function, then how will I use the salt string?
I was missing following line:
#import <CommonCrypto/CommonHMAC.h>
Actually, < CommonCrypto / CommonCryptor.h > was already added in my code. So, at first look, I thought that there is no worry about importing particular header file. But, suddenly I realize that I will have to import another header file.
Example of SHA256 HMAC:
+ (NSData *)doHmac:(NSData *)dataIn key:(NSData *)salt
{
NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
CCHmac( kCCHmacAlgSHA256,
salt.bytes, salt.length,
dataIn.bytes, dataIn.length,
macOut.mutableBytes);
return macOut;
}

How can I hash a NSString to SHA512

I have one quick question...
I am building a social media network site app and I need to hash the password NSString. How would I accomplish this? I have the password field on the app and would like to hash the string and encode it in SHA512 for the POST request.
Thanks in advance,
TechnologyGuy
Already answered: hash a password string using SHA512 like C#
But here's the copy-pasted code:
#include <CommonCrypto/CommonDigest.h>
+ (NSString *) createSHA512:(NSString *)source {
const char *s = [source cStringUsingEncoding:NSASCIIStringEncoding];
NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA512_DIGEST_LENGTH] = {0};
CC_SHA512(keyData.bytes, keyData.length, digest);
NSData *out = [NSData dataWithBytes:digest length:CC_SHA512_DIGEST_LENGTH];
return [out description];
}
Or if you prefer a hashed output, try this:
+(NSString *)createSHA512:(NSString *)string
{
const char *cstr = [string cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:string.length];
uint8_t digest[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(data.bytes, data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return output;
}
+ (NSData *)sha512:(NSData *)data {
unsigned char hash[CC_SHA512_DIGEST_LENGTH];
if ( CC_SHA512([data bytes], [data length], hash) ) {
NSData *sha1 = [NSData dataWithBytes:hash length:CC_SHA512_DIGEST_LENGTH];
return sha1;
}
return nil;
}
Put this in a category on NSData, or use it whatever way you like, the code remains the same.
You should've researched your question. I found an answer in one google search.

xcode ios HMAC SHA 256 hashing

So I'm trying to figure out how to do a hmacshad256 hash on ios as that's the hash I did for the wcf service api I made. I've been trying to look for some info about it but would usually just end up getting a SHA-256 hash.
This is the only reference I have:
Need to generate HMAC SHA256 hash in Objective C as in Java
And I'm not sure if that's the only way to do it (importing a java hmac class)
Any help is appreciated.
Thanks!
NSString * parameters = #"string to hash"
NSString *salt = #"saltStringHere";
NSData *saltData = [salt dataUsingEncoding:NSUTF8StringEncoding];
NSData *paramData = [parameters dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData* hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH ];
CCHmac(kCCHmacAlgSHA256, saltData.bytes, saltData.length, paramData.bytes, paramData.length, hash.mutableBytes);
NSString *base64Hash = [hash base64Encoding];
and also
#import <CommonCrypto/CommonHMAC.h>
Since base64Encoding is deprecated from iOS 7.0, the last line should be:
NSString *base64Hash = [hash base64EncodedStringWithOptions:0];
Here is the solution I'm submitting that I put together from other answers on the matter:
This is easily adapted to other hash types by changing CC_SHA256_DIGEST_LENGTH and kCCHmacAlgSHA256.
If you're interested in doing that, check out the CommonDigest.h file within the CommonCrypto library.
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCrypto.h>
+ (NSString *)hmac:(NSString *)plaintext withKey:(NSString *)key
{
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [plaintext cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];
const unsigned char *buffer = (const unsigned char *)[HMACData bytes];
NSMutableString *HMAC = [NSMutableString stringWithCapacity:HMACData.length * 2];
for (int i = 0; i < HMACData.length; ++i){
[HMAC appendFormat:#"%02x", buffer[i]];
}
return HMAC;
}
This has been tested on iOS 8.x and iOS 7.x
+ (NSString *)hmacSHA256EncryptString{
NSString * parameterSecret = #"input secret key";
NSString *plainString = #"input encrypt content string";
const char *secretKey = [parameterSecret cStringUsingEncoding:NSUTF8StringEncoding];
const char *plainData = [plainString cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, secretKey, strlen(secretKey), plainData, strlen(plainData), cHMAC);
NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];
const unsigned char *bufferChar = (const unsigned char *)[HMACData bytes];
NSMutableString *hmacString = [NSMutableString stringWithCapacity:HMACData.length * 2];
for (int i = 0; i < HMACData.length; ++i){
[hmacString appendFormat:#"%02x", bufferChar[i]];
}
return hmacString;
}

Resources