Amadiere.com

Fourteen and a half crazy frog burpers

10th February 2011

C#.NET & Classic ASP Password Hashing

Filed under: ASP.NET,C#,Classic ASP — Tags: , , , , — Alex Holt @ 9:02 pm

One of the things I’ve recently been working on is a solution to allow both a .NET application and a legacy VBScript / Classic ASP to be able to validate a specific username / password combination, comparing two hashed passwords. In the process, I discovered (with the help of Google and StackOverflow) that accessing .NET objects from Classic ASP isn’t really all that hard! But to the issue at hand: Password Hashing! Sorting this out from the .NET side was relatively easy. For the purpose of this post, here is roughly what I have at the moment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
 
namespace Amadiere.Com.Utilities
{
    public static class Cryptography
    {
        /// <summary>
        /// Encrypts a password based on the passed in Encryption method (SHA512Managed is a good starting
        /// point if you don't know which to use).
        /// </summary>
        /// <remarks>
        /// The passwordSalt parameter is required to ensure that rainbow tables cannot be used to
        /// lookup all usernames if the salt is discovered. This salt is OK to store in the database,
        /// along with the hashedPassword generated by this function.
        /// </remarks>
        /// <param name="password">The password to be encrypted.</param>
        /// <param name="passwordSalt">The individual grain of salt for that password.</param>
        /// <param name="method">The method by which to encrypt.</param>
        /// <returns>An string representing the hashed password (88 characters long).</returns>
        public static string Hash(string password, string passwordSalt, HashMethods method)
        {
            string siteWideSalt = "THIS IS A SITE WIDE SALT, BUT COULD BE A GUID";
            string encryptedPassword;
            switch (method)
            {
                default:
                    encryptedPassword = HashSHA512Managed(siteWideSalt + password + passwordSalt);
                    break;
            }
            return encryptedPassword;
        }
 
        /// <summary>
        /// One-way encrypts the password into oblivion. If the same password and salt are provided, the
        /// same end string will be churned out the other end of this sausage machine.
        /// </summary>
        /// <see cref="http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha512managed.aspx"/>
        /// <example>HashSHA512Managed("bobsYourUncle_SALT-GOES-HERE");</example>
        /// <param name="password">Unencoded pre-salted password.</param>
        /// <returns>An 88 character string, representing the originally encoded password.</returns>
        private static string HashSHA512Managed(string saltedPassword)
        {
            UnicodeEncoding uniEncode = new UnicodeEncoding();
            SHA512Managed sha = new SHA512Managed();
            byte[] bytePassword = uniEncode.GetBytes(saltedPassword);
            byte[] hash = sha.ComputeHash(bytePassword);
            return Convert.ToBase64String(hash);
        }
    }
 
    public enum HashMethods
    {
        SHA512
    }
}

The Classic ASP side of things wasn’t as easy. There are no built in libraries for SHA512 (or in fact, many other password hashing algorithms). So I had a few options on how I was to proceed:

  • Abandon my choice of SHA512 and go with MD5 where there seemed to be a bit more usage in the community. I was reluctant to do this because it isn’t as good as SHA512.
  • Copy some code sample that has been created by someone else, that I either have to accept is OK, or spend a good deal of time understanding it and breaking it down bit by bit.
  • Create a custom COM object in .NET, register it in the GAC and reference that via Classic ASP.
  • Access the .NET functions directly from Classic ASP.

The last option won – because it worked, and because it meant a lot less maintenance and praying for things to keep working. This is the code that pretty much does the same as the above .NET code, but in VBScript.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Function Hash(strPassword, strIndividualSalt)
 
  Const strSiteWideSalt = "THIS IS A SITE WIDE SALT, BUT COULD BE A GUID"
  Hash = HashSHA512Managed(strSiteWideSalt & strPassword & strIndividualSalt)
 
End Function
 
Function HashSHA512Managed(saltedPassword)
 
  Dim objMD5, objUTF8
  Dim arrByte
  Dim strHash
  Set objUnicode = CreateObject("System.Text.UnicodeEncoding")
  Set objSHA512 = Server.CreateObject("System.Security.Cryptography.SHA512Managed")
 
  arrByte = objUnicode.GetBytes_4(saltedPassword)
  strHash = objSHA512.ComputeHash_2((arrByte))
 
  HashSHA512Managed = ToBase64String(strHash)
 
End Function
 
Function ToBase64String(rabyt)
 
  'Ref: http://stackoverflow.com/questions/1118947/converting-binary-file-to-base64-string
  Dim xml: Set xml = CreateObject("MSXML2.DOMDocument.3.0")
  xml.LoadXml ""
  xml.documentElement.dataType = "bin.base64"
  xml.documentElement.nodeTypedValue = rabyt
  ToBase64String = Replace(xml.documentElement.Text,VbLf, "")
 
End Function

As you can see in the VBScript example, I can create the .NET objects as I would any other type of object in VBScript, the difference comes in how I use them. Normally, in C#, you’d simply use ComputeHash() and there would be a number of overloads for you to choose from. As VBScript doesn’t have the concept of overloading, you have to use a crazy-mad way of accessing the specific overload you want – using an underscore. I’ve not really come up with a full-proof way of working out which is which (though, if I’m honest, I didn’t try much). I did however find out that they started ComputeHash(), ComputeHash_1() and ComputeHash_2() – I assume the numbers resemble the order they appear in Visual Studio when using intellisense for C# – but trial and error is normally good enough.

Hope this is of use to someone else! If anything, I’m sure I’ll find a need to do this again someday and I’m sure it’ll be useful for then! All this hashing has made me hungry!

Hashing passwords is hard! Let's eat!

Hashing passwords is hard! Let's eat!

10th September 2010

Isolated Storage on Windows Phone 7

Filed under: C#,Databases,Windows Phone 7 — Tags: , , , — Alex Holt @ 9:30 pm

One of the most amazing omissions from the Windows Phone 7 OS is an SQL Server of some description that applications can use (I think there is a SQL Server Compact edition baked into the build, but it’s only exposed to the native apps). This leaves anyone familiar with doing all their storage via relational databases in a bit of a lurch.

Having a look around, there were a few work-arounds, namely third party libraries such as Perst & Sterling. These act as a layer of abstraction that allow you to use LINQ to access your objects and could be of benefit for some of the more complex applications. I found both of them to have their drawbacks.

Perst: From McObject is one alternative, but if you plan on doing a commercial application, you should bare in mind their licensing, of which, their FAQ says:

No, Perst is not free. McObject Perst is available under a dual license. Under the GPL, you may evaluate the source code free of charge and you may use Perst free of charge in an application for which the source code is also freely available. If you wish to use a Perst in an application but do not or cannot redistribute your application source code, you can use Perst under a commercial license.

Sterling: This seemed promising, but I had a number of issues getting the code to work (it was late, in fairness) I decided to give up.

In reality though, most applications that are going to be made don’t need any complicated database structure behind them. Database implementations are most likely going to be overkill. This is where I decided to do what probably the majority of WP7 developers have decided to do, and “Roll-Their-Own” database solution. Mine is based on a general accepted practice, using XML Serialisation to store my POCOs. While it might have limitations and performance issues later down the line, for now – it’s performing very admirably and there seemed no point in premature optimisation just yet.

My Solution

The main class I created (MyDataContext.cs) contains the functions for both saving and loading the data, as well as the ‘schema’ for the entire database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Collections.Generic;
using IsolatedExampleApp.Data.Models;
using System.IO.IsolatedStorage;
using System.IO;
using System.Xml.Serialization;
 
namespace IsolatedExampleApp.Data
{
  public class IsolatedDatabase
  {
    public IsolatedDatabase()
    {
      // For each model that is a list item, you need to add a initialising statement to the Constructor
      Albums = new List();
      Artists = new List();
    }
 
    // These properties effectively form the publicly viewable schema of the database.
    public List Albums { get; set; }
    public List Artists { get; set; }
    public Options Options { get; set; }
 
    public void Load()
    {
      using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
      using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("IsolatedExampleApp.txt", FileMode.OpenOrCreate, FileAccess.Read, store))
      using (StreamReader reader = new StreamReader(stream))
      {
        XmlSerializer serializer = new XmlSerializer(typeof(IsolatedDatabase));
        var unserialized = reader.EndOfStream ? new IsolatedDatabase() : (IsolatedDatabase)serializer.Deserialize(reader);
 
        // Each schema is repopulated with information when the app is loaded.
        Albums = unserialized.Albums;
        Artists = unserialized.Artists;
        Options = unserialized.Options;
      }
    }
 
    public bool Save()
    {
      try
      {
        using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
        using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("IsolatedExampleApp.txt", FileMode.Create, FileAccess.Write, store))
        {
          XmlSerializer serializer = new XmlSerializer(typeof(IsolatedDatabase));
          serializer.Serialize(stream, this);
        }
        return true;
      }
      catch (Exception ex)
      {
        return false;
      }
    }
  }
}

As you can see from the code above, as you develop more data stores, the code needs updating in multiple locations.

  • Properties need setting for each one (they are the publicly available access points for the data).
  • Any LISTS<> require their lists initialised by the Constructor method.
  • When the data is ‘Load()’ed, each property must have it’s values manually set.
  • All the Models still need defining elsewhere in your application (in my example above, they are in the IsolatedExampleApp.Data.Models namespace.

If you can overlook this repeated typing, then this seems to be a good starting point for persisting data in your Windows Phone 7 Application. To use it should then be fairly straight forward.

_db = new IsolatedDatabase();
_db.Load();
 
// Adding an album...
_db.Albums.Add(newAlbum);
_db.Save();
 
// Deleting an album...
_db.Albums.Remove(deleteAlbum);
_db.Save();
 
// Add or Update an album...
Album existingAlbum = _db.Albums.Where(x => x.ID == album.ID).FirstOrDefault();
if (existingAlbum != null)
{
  Delete(existingAlbum);
}
Add(album);
_db.Save();
 
// Or just getting a specific album...
IEnumerable albums = _db.Albums as IEnumerable;
return albums.Where(x => x.ID == id).FirstOrDefault();

Any feedback, thoughts, options and optimisations for the above code will be well received. Happy isolating!

6th April 2010

Development SMTP Servers for IIS7.5 on Windows 7

Filed under: ASP.NET,C# — Tags: , , , , , — Alex Holt @ 3:43 pm

I’ve had one of them days. You know? That “simple task” that spiralled out of control and resulted in me losing half a day to it’s tricks! That task? It was sending an email from an ASP.NET (MVC2) application. Previously, I’ve always done this via setting up IIS and the SMTP server in there, but for some reason, Microsoft decided they didn’t want to include the SMTP Server in Windows 7 anymore (even ‘Ultimate’ – it might also be the case for Windows Vista). So, I had to find an alternative.

There were a few options available to me:

  • SMTP Server on Localhost: This was the obvious choice, but after trying Mercury Mail and it’s quarter of a million settings as it installed (I’m no Email Admin, so didn’t know the answer to all of them). It didn’t work and I’m not sure why. To rub salt into the would, there was no uninstall either – it proper irritated me and I gave up using it out of principal.
  • SMTP Server on Localhost that is really just a Relay. Well, sounded good – but again, it was designed by people with bigger brains than me and it failed to send to what I thought was a correctly configured IIS7.5 config pointing to my GMail account.
  • Fake Server: Something that doesn’t actually send emails, but pretends to.

The last one is the one I eventually choose and boy am I glad I did! I downloaded the excellent SMTP 4 DEV from Codeplex

  1. I don’t have 100′s of emails cluttering up my email box for starters. Win!
  2. It was so easy to set-up and it worked perfectly without a change to my code. Win!
  3. It’s free. Win!

Here is some fake code that should send an email to the localhost.

MailMessage emailMessage = new MailMessage();
string messageBody = "This is the content of the email will be awesome!";
 
emailMessage.Body = messageBody;
emailMessage.Priority = MailPriority.Normal;
emailMessage.From = new MailAddress("no-reply@amadiere.com"); // obviously, this email address doesn't exist :)
emailMessage.Subject = "The answer is 42";
emailMessage.IsBodyHtml = false;
 
SmtpClient mSmtpClient = new SmtpClient();
mSmtpClient.Host = "127.0.0.1";  // localhost
mSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
 
mSmtpClient.Send(emailMessage);
Older Posts »

Theme designed & built for Amadiere.com by Alex Holt. Powered by WordPress