hash a password string using SHA512 like C# - iphone

I am developing logon function for my iPhone Application, so I want to hash the password using the SHA512 hashing algorithm then get the result as NSString (the result should be the same with SHA512 in C#). After spending a lot of time in the internet, I still not find out the solution yet! :(
Is there anyone has the solution and sample code, please help me!
Thanks a lot!
[Update]
In my C# code, the password is stored using SecureString, so maybe it's cause make different byte array between objective-c and C#

This function will hash a string using SHA512. The resulting string is a hex representation of the hash:
+ (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];
}
Don't forget to include the correct header:
#include <CommonCrypto/CommonDigest.h>

I am using this one.
It matches PHP SHA512 algorithm output:
<?php `hash('sha512', 'The quick brown fox jumped over the lazy dog.');` ?>
Objective-C code:
+(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;
}

Related

Encryption into a 32-bit string in Unicode (UCS-16) format by MD5 algorithm

I have this code to generate MD5 Hash in UTF-8 format :
const char* str = [clearPassword UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, strlen(str), result);
NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
for(int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) {
[ret appendFormat:#"%02x",result[i]];
}
return ret;
But my requirement needs to have 32-bit Unicode Hash.
lets say the string is "admin". using my code, I'll have "21232f297a57a5a743894a0e4a801fc3" which is wrong.
I used some online generators to get unicode hash and I got "19a2854144b63a8f7617a6f225019b12" which exactly what I want.
Which part of my code needs to be changed?
Try this:
NSData *utf16data = [clearPassword dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5([utf16data bytes], [utf16data length], result);
NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
for(int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) {
[ret appendFormat:#"%02x",result[i]];
}
return ret;

How to read bytes from NSData

Can anyone suggest a method to read bytes from NSData (like read function in #interface NSInputStream : NSStream)
How to read binary bytes in NSData? may help you:
NSString *path = #"…put the path to your file here…";
NSData * fileData = [NSData dataWithContentsOfFile: path];
const char* fileBytes = (const char*)[fileData bytes];
NSUInteger length = [fileData length];
NSUInteger index;
for (index = 0; index<length; index++) {
char aByte = fileBytes[index];
//Do something with each byte
}
You can also create an NSInputStream from an NSData object, if you need the read interface:
NSData *data = ...;
NSInputStream *readData = [[NSInputStream alloc] initWithData:data];
[readData open];
However, you should be aware that initWithData copies the contents of data.
One of the simplest ways is to use NSData getBytes:range:.
NSData *data = ...;
char buffer[numberOfBytes];
[data getBytes:buffer range:NSMakeRange(position, numberOfBytes)];
where position and length is the position you want to read from in NSData and the length is how many bytes you want to read. No need to copy.
Alex already mentioned NSData getBytes:range: but there is also NSData getBytes:length: which starts from the first byte.
NSData *data = ...;
char buffer[numberOfBytes];
[data getBytes:buffer length:numberOfBytes];
May way of doing that..
do not forget to free byte array after usage.
NSData* dat = //your code
NSLog(#"Receive from Peripheral: %#",dat);
NSUInteger len = [dat length];
Byte *bytedata = (Byte*)malloc(len);
[dat getBytes:bytedata length:len];
int p = 0;
while(p < len)
{
printf("%02x",bytedata[p]);
if(p!=len-1)
{
printf("-");
}//printf("%c",bytedata[p]);
p++;
}
printf("\n");
// byte array manipulation
free(bytedata);

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];
}

Error during insert binary data in Ultralite database iPhone

Hi I am writing a iphone application where I need to store binary data i.e.; image in the Ultralite database.
I am using following code for this purpose.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"file_name" ofType:#"png"];
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSUInteger len = [data length];
ul_binary *byteData = (ul_binary*)malloc(len);
memcpy(byteData, [data bytes], len);
ULTable *table = connection->OpenTable("NAMES");
if(table->InsertBegin()){
table->SetInt(1, (maxId+1));
table->SetString(2, [name UTF8String]);
table->SetBinary(3, byteData);
table->Insert();
table->Close();
connection->Commit();
}
This code is giving error 'EXC_BAD_ERROR' on line::
table->SetBinary(3, byteData);
This code works fine if i comment this line.
Any help would be appreciated!
Thanks
The definition of ul_binary is this:
typedef struct ul_binary {
/// The number of bytes in the value.
ul_length len;
/// The actual data to be set (for insert) or that was fetched (for select).
ul_byte data[ MAX_UL_BINARY ];
} ul_binary, * p_ul_binary;
So it's a struct. By simply doing the memcpy as you do, you also overwrite the len field and everythings messed up. So here's how you should do it (as far as I can see):
ul_binary *byteData = (ul_binary *)malloc(sizeof(ul_binary));
memcpy(&byteData->data, [data bytes], len);
byteData->len = len;
You also need to check that len <= MAX_UL_BINARY before you try to allocate the memory. And don't forget to free(byteData);.

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