Feb 05

Hashing library for iOS and how it can be used in conjunction with .Net hashing

I’m working on an iPhone / iPad app that needs to be able to authenticate itself to the server from which it requests data. The users of the app will have an account with the website so they will already have a username / password. There is no SSL functionality, so I needed a way to authenticate over plaintext without giving away the password or even the hash of it.

Let’s talk about what the webserver does in relation to storing the password. It doesn’t actually store the password.  It stores a hashed value where the actual password was combined with a salt (random string of a descent length) and that combined string was hashed using SHA256. The result is stored as the “password” for the user and the salt used to compute the hash is also stored for that user. When the user logs in the password they send (using ssl, so it is encrypted between the user and server) is combined with the stored salt and hashed. If the result is the same as the stored hash then the user is authenticated, otherwise they are not.

Here’s a little helper class written in C# for doing the Hash. It’s server side and .net specific.


#region HashingLogic
public class Hash
 {
 public Hash() { }
public enum HashType : int
 {
 MD5,
 SHA1,
 SHA256,
 SHA512
 }
public static string GetHash(string text, HashType hashType)
 {
 HashAlgorithm _algorithm;
 switch (hashType)
 {
 case HashType.MD5:
 _algorithm = MD5.Create();
 break;
 case HashType.SHA1:
 _algorithm = SHA1.Create();
 break;
 case HashType.SHA256:
 _algorithm = SHA256.Create();
 break;
 case HashType.SHA512:
 _algorithm = SHA512.Create();
 break;
 default:
 throw new ArgumentException("Invalid hash type", "hashType");
 }
byte[] bytes = Encoding.Unicode.GetBytes(text);
 byte[] hash = _algorithm.ComputeHash(bytes);
string hashString = string.Empty;
 foreach (byte x in hash)
 {
 hashString += String.Format("{0:x2}", x);
 }
 return hashString;
 }
public static bool CheckHash(string original, string hashString, HashType hashType)
 {
 string originalHash = GetHash(original, hashType);
 return (originalHash == hashString);
 }
}
 #endregion

And here’s the webserver checking the Hash. It should be pretty easy to see how to store it as well when a user sets their password in the first place.

 // ran a query that returned the hashed password and salt for the user in question
 // note: password is the value sent by the user trying to log in
 string the_hashed_password = dt.Rows[0]["vcHashedPass"].ToString().Trim();
 string the_salt = dt.Rows[0]["vcPassSalt"].ToString().Trim();
 string the_salted_password = password.Trim() + the_salt;
 string hashedvalue = Hash.GetHash(the_salted_password, Hash.HashType.SHA256);
     if (hashedvalue == the_hashed_password)
         loginSuccessful = true;

 

Now that we have the background, I can talk about what really screwed with me. I was trying to implement part of this on the iOS side. , but I was getting a different value back for my hash. I used a Hash library for iOS from this site. It was easy to use. Just copy the files to your project and import the .h into whatever file you need to do hashing.  Before hashing an NSString you must first convert it to an NSData. But this conversion requires you to specify the encoding. To use it in conjunction with the .Net helper class above you have to choose the right encoding or it will has to the wrong value. Code first, then discussion.

NSString *usernameex = [keychainwrapper objectForKey:(id)kSecAttrAccount];
 NSString *passwordex = [keychainwrapper objectForKey:(id)kSecValueData];
 // I'm hardcoding the salt for this example, now we need to talk to the server  to see if it will let us log in with it
NSString *retrievedSalt = [NSString stringWithFormat:@"b3b5c979-3438-4f56-aa1a-1d85bda78b7e"];
 NSString *saltedpassword =  [NSString stringWithFormat:@"%@%@", passwordex, retrievedSalt];
// Webserver thinks that hashed(password+salt)  =
 // 14083e601f136a42bb17f37a6dedfd03c1f53f2c93f2cc886de5b44ed4a452c1 -- looking for
// but this library was returning various results... here's one
 // ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e -- getting
 // there are lots of example of how the "encoding" can be done and what the hashed value that results is
 // I included them in this sample code because I had to try a ton to finally find the one that matched the .net
HashValue *hashvalue;
//NSUTF16StringEncoding 762ce0d893b64032f11562e4ee0be3f4ed08ca6b801ab892d319af3942ca788c
 NSData* datasaltedpassword0a=[saltedpassword dataUsingEncoding:NSUTF16StringEncoding];
 hashvalue = [HashValue sha256HashWithData:datasaltedpassword0a];
 ASLog(@"hashedvalue0a - %@", hashvalue.description); // password - whatever you entered
NSData* datasaltedpassword0b=[saltedpassword dataUsingEncoding:NSUTF16BigEndianStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0b];
ASLog(@"hashedvalue0b - %@", hashvalue.description); // password - whatever you entered
NSData* datasaltedpassword0c=[saltedpassword dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0c];
ASLog(@"hashedvalue0c - %@", hashvalue.description); // password - whatever you entered
NSData* datasaltedpassword0d=[saltedpassword dataUsingEncoding:NSUTF32StringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0d];
ASLog(@"hashedvalue0d - %@", hashvalue.description); // password - whatever you entered
NSData* datasaltedpassword0e=[saltedpassword dataUsingEncoding:NSUTF32BigEndianStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0e];
ASLog(@"hashedvalue0e - %@", hashvalue.description); // password - whatever you entered
NSData* datasaltedpassword0f=[saltedpassword dataUsingEncoding:NSUTF32LittleEndianStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword0f];
ASLog(@"hashedvalue0f - %@", hashvalue.description); // password - whatever you entered
//NSUTF8StringEncoding
NSData* datasaltedpassword1=[saltedpassword dataUsingEncoding:NSUTF8StringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword1];
ASLog(@"hashedvalue1 - %@", hashvalue.description); // password - whatever you entered
//[NSString defaultCStringEncoding]
NSData* datasaltedpassword2=[saltedpassword dataUsingEncoding:[NSString defaultCStringEncoding]];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword2];
ASLog(@"hashedvalue2 - %@", hashvalue.description); // password - whatever you entered
//NSUnicodeStringEncoding allowLossyConversion:NO
NSData* datasaltedpassword3=[saltedpassword dataUsingEncoding:NSUnicodeStringEncoding allowLossyConversion:NO];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword3];
ASLog(@"hashedvalue3 - %@", hashvalue.description); // password - whatever you entered
//NSWindowsCP1252StringEncoding
NSData* datasaltedpassword4=[saltedpassword dataUsingEncoding:NSWindowsCP1252StringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword4];
ASLog(@"hashedvalue4 - %@", hashvalue.description); // password - whatever you entered
//NSMacOSRomanStringEncoding
NSData* datasaltedpassword5=[saltedpassword dataUsingEncoding:NSMacOSRomanStringEncoding];
hashvalue = [HashValue sha256HashWithData:datasaltedpassword5];
ASLog(@"hashedvalue5 - %@", hashvalue.description); // password - whatever you entered
ASLog(@"targetvalue - 14083e601f136a42bb17f37a6dedfd03c1f53f2c93f2cc886de5b44ed4a452c1", hashvalue.description); // password - whatever you entered

And the output:

2012-02-05 16:13:38.077 [11082:560f] LoginViewController.m:121 -[LoginViewController workOfDoLogin] password – ocelot

2012-02-05 16:13:38.078 [11082:560f] LoginViewController.m:140 -[LoginViewController workOfDoLogin] salt – b3b5c979-3438-4f56-aa1a-1d85bda78b7e

2012-02-05 16:13:38.078 [11082:560f] LoginViewController.m:144 -[LoginViewController workOfDoLogin] saltedpassword – ocelotb3b5c979-3438-4f56-aa1a-1d85bda78b7e

2012-02-05 16:13:38.080 [11082:560f] LoginViewController.m:152 -[LoginViewController workOfDoLogin] hashedvalue0a – 762ce0d893b64032f11562e4ee0be3f4ed08ca6b801ab892d319af3942ca788c

2012-02-05 16:13:38.080 [11082:560f] LoginViewController.m:156 -[LoginViewController workOfDoLogin] hashedvalue0b – df7e828a1df0664ff42756960ab7f63e83f0504437c59286e217df32147d8815

2012-02-05 16:13:38.081 [11082:560f] LoginViewController.m:160 -[LoginViewController workOfDoLogin] hashedvalue0c – 14083e601f136a42bb17f37a6dedfd03c1f53f2c93f2cc886de5b44ed4a452c1

2012-02-05 16:13:38.082 [11082:560f] LoginViewController.m:164 -[LoginViewController workOfDoLogin] hashedvalue0d – 4276b8d7ff791492f537379bf7353095d8ce40c717f15dc242f2847b376b88de

2012-02-05 16:13:38.083 [11082:560f] LoginViewController.m:168 -[LoginViewController workOfDoLogin] hashedvalue0e – 45838174fdf6cb95b7ed6bdbd7409f065c75f12958e58ae84ec5d28235b6cf0e

2012-02-05 16:13:38.083 [11082:560f] LoginViewController.m:172 -[LoginViewController workOfDoLogin] hashedvalue0f – 492adfab98090cf9319684aa707d368a2689495480a59ffd7a9b2a514ea9362d

2012-02-05 16:13:38.084 [11082:560f] LoginViewController.m:178 -[LoginViewController workOfDoLogin] hashedvalue1 – ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e

2012-02-05 16:13:38.085 [11082:560f] LoginViewController.m:183 -[LoginViewController workOfDoLogin] hashedvalue2 – ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e

2012-02-05 16:13:38.086 [11082:560f] LoginViewController.m:188 -[LoginViewController workOfDoLogin] hashedvalue3 – 762ce0d893b64032f11562e4ee0be3f4ed08ca6b801ab892d319af3942ca788c

2012-02-05 16:13:38.086 [11082:560f] LoginViewController.m:193 -[LoginViewController workOfDoLogin] hashedvalue4 – ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e

2012-02-05 16:13:38.087 [11082:560f] LoginViewController.m:198 -[LoginViewController workOfDoLogin] hashedvalue5 – ed87d50a50937361f17f9b3c32c6db04e6b7779e5f3c42dfa20e44cac7bf112e

2012-02-05 16:13:38.088 [11082:560f] LoginViewController.m:201 -[LoginViewController workOfDoLogin] targetvalue – 14083e601f136a42bb17f37a6dedfd03c1f53f2c93f2cc886de5b44ed4a452c1

 

The right Encoding to use on the iOS side was “NSUTF16LittleEndianStringEncoding”. I had to do all of those tests to finally find which one matched the values being produced on the web side (.Net)… so just keep in mind that if your getting two different hashes then you might need to use a different Encoding during the conversion from String to Byte / Data in order to make them sync up.

 

Feb 04

Hiding the Keyboard when touching background

If you are working on an iOS app and have the need for the user the enter input then you usually use a textfield or textview. I was working on a login screen and had a very annoying experience where the keyboard wouldn’t go away after I had finished entering my text. What was especially annoying was that I had encountered it before and had simply forgotten how to resolve it. So I’m writing this up for myself or anyone else who needs the info.

All you have to do is make sure that your view has ‘User Interaction Enabled’ checked under the ‘Attributes Inspector’. Then add the following block of code to your view’s implementation. You can see that I have two textFields called txtUsername and txtPassword. You’ll want to change them to match the names of all the text fields on your form (you don’t know which one is actually the first responder at the time, but from what I’ve read it doesn’t hurt to resign if you are not it anyway). So that’s it.

– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

UITouch * touch = [touches anyObject];

if(touch.phase == UITouchPhaseBegan) {

[self.txtPassword resignFirstResponder];

[self.txtUserName resignFirstResponder];

}

}

Here’s another place that discusses it in a bit more detail.

I’ll also mention that some people use a hidden button the size of the view. Then they tie that button to a “hideKeyboard” method. That solution is also discussed in that thread. I found a better explanation of it a Sams Publishing teach yourself Iphone Development book, but the discussion on that thread will suffice. For my own reference it is on page 179-182. It also discusses how to release the keyboard when the “Done” button is pressed. You will probably want to implement BOTH.

Oct 02

iPhone and iPad naming conventions, icon descriptions, and icon sizes

The below table is a description of iphone icons and ipad icons, what they’re sizes and should be, and what their standardized names are. This information is all over, but the a thorough and yet concise version (and what i based the below on) can be found here.

Name Size (pixels) Platform
Icon.png 57 x 57 Universial application icon
Icon-settings.png 29 x 29 Universial application icon for settings area. Alternative name: Icon-Small.png
Icon~ipad.png 72 x 72 iPad application icon. Alternative name: Icon-72.png Add some smaller (iPad doc: 64×64, other optional 32×32, 24×24, 16×16) custom icons to your project. See comments.
Icon-spot~ipad.png 50 x 50 iPad icon for spotlight search. Alternative name: Icon-Small-50.png iPhone OS trims 1 pixel from each side and adds a drop shadow. The actual size is 48×48 pixels.
iTunesArtwork.png 512 x 512 Universial application icon for iTunes App Store. Uploaded separately to iTunes. It’s included in the app bundle too, file name: iTunesArtwork. In an iPad application iPhone OS uses this image to generate the large (320×320) document icon if it is not supplied otherwise.
Default.png 320 (w) x 480 (h) iPhone/iPod 2, 3 portrait launch image
Default@2x.png 640 (w) x 960 (h) iPhone 4 hi-res portrait launch image
Default~ipad.png 768 (w) x 1004 (h) iPad. Specifies the default portrait launch image. This image is used if a more specific image is not available. Use full size template (768×1024) to design this launch image. The 20 pixels height statusbar is on by default and occupies the top of the screen, aka the 1004 rows vs. 1024.
Optional icons and images:
Icon@2x.png 114 x 114 iPhone 4 hi-res application icon
Icon-settings@2x.png 58 x 58 iPhone 4 hi-res application icon for settings/search area
Icon-doc.png 22 (w) x 29 (h) Universial document icon
Icon-doc@2x.png 44 (w) x 58 (h) iPhone 4 hi-res document icon
Icon-doc~ipad.png 64 x 64 iPad document icon (small)
Icon-doc320~ipad.png 320 x 320 iPad document icon (large)
Background-xxx.png 320 (w) x 480 (h)
640 (w) x 960 (h)
768 (w) x 1024 (h)
iPhone/iPod Touch 2, 3 background image,
iPhone 4 background image, full size
iPad background image, full size. For most projects the status bar is hidden, so use full screen size by default.
Default-PortraitUpsideDown~ipad.png 768 (w) x 1004 (h) iPad. Specifies an upside-down portrait version of the launch image. The height of this image should be 1004 pixels and the width should be 768. This file takes precedence over the Default-Portrait.png image file for this specific orientation.
Default-LandscapeLeft~ipad.png 1024 (w) x 748 (h) iPad. Specifies a left-oriented landscape version of the launch image. The height of this image should be 748 pixels and the width should be 1024. This file takes precedence over the Default-Landscape.png image file for this specific orientation.
Default-LandscapeRight~ipad.png 1024 (w) x 748 (h) iPad. Specifies a right-oriented landscape version of the launch image. The height of this image should be 748 pixels and the width should be 1024. This file takes precedence over the Default-Landscape.png image file for this specific orientation.
Default-Portrait~ipad.png 768 (w) x 1004 (h) iPad. Specifies the generic portrait version of the launch image. The height of this image should be 1004 pixels and the width should be 768. This image is used for right side-up portrait orientations and takes precedence over the Default~ipad.png image file. If a Default-PortraitUpsideDown.png image file is not specified, this file is also used for upside-down portrait orientations as well.
Default-Landscape~ipad.png 1024 (w) x 748 (h) iPad. Specifies the generic landscape version of the launch image. The height of this image should be 748 pixels and the width should be 1024. If a Default-LandscapeLet.png or Default-LandscapeRight.png image file is not specified, this image is used instead. This image takes precedence over the Default.png image file.
Sep 29

How to let your iphone or ipad apps check for network access – reachability

I have recently been working on a new iOS app for the iPhone and I ran into a couple of issues. I don’t really have time to go over them all in this post, but I did want to document one of them because I hear it can be a big deal as far as getting your app approved by Apple. The issue is that of making sure you handle things gracefully if the user’s phone is unable to connect to the internet and they try to do something that does require a connection.

The way I decided to handle it was to use the reachability collection provided by apple. I downloaded the reachability sample from Apple and then copied and imported the 4 files from the “classes” directory into my project.

Then I added the “SystemConfiguration.framework” to my project.

Now I have all of the prereqs for my solution. The next thing I did was I created a NetworkReachabilityTest class with NSObject as its base class. I added a single method called “isNetworkReachableWithAlert” that returned a bool and included one parameter. The parameter specified whether it should automatically pop up an alert box in case of a lack of network connectivity.

I chose to do it this way (as a dumb small class) so I didn’t have to copy the code for this method into every page. Plus it gives me the flexibility to easily reuse it in future projects. So now, before I do something that requires network connectivity I instantiate an instance of this class, I do the check, and if the connection is there I do the work. If the connection is not there I can bail out instead.

Here’s the code (some of this code was included in the example and some was found here around post 29 or 30:

-(BOOL) isNetworkReachableWithAlert:(BOOL)bshowalert

{

Reachability *r = [Reachability reachabilityWithHostName:@”www.signandtrade.com”];

NetworkStatus internetStatus = [r currentReachabilityStatus];

if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN))

{

if (bshowalert)

{

UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:@”No Internet Connection” message:@”An internet connection via WiFi or cellular network is required for this portion of the app to work.” delegate:self cancelButtonTitle:@”Ok”   otherButtonTitles:nil];

[myAlert show];

[myAlert release];

}

return NO;

}

return YES;

}

That’s in the implementation file  of my simple class and it is basically the only thing there! And it does everything we need.

And here it is in use:

NetworkReachabilityTest *nrt = [[NetworkReachabilityTest alloc] init];

if ([nrt isNetworkReachableWithAlert:YES])

{

// logic that requires or includes web activity here

}

[nrt release];

Hope that helps. Hope it makes sense. Better ideas or improvements on it are welcome, I just wanted to give someone a simple example of something that I know works  along with the steps I took to make it work.