About the author

J Sawyer is a developer based in Houston, TX and loves to write code, especially ASP.NET and other web-related stuff.

He also loves to ride his Kawasaki Ninja.

But he doesn't code and ride at the same time.

Calendar

<<  March 2010  >>
MoTuWeThFrSaSu
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar

Blog Code Samples ...

February 24, 2008 4:48 PM

Well, I just finished creating a resource in MSDN Code Gallery.  If you haven't checked this out yet, you really need to. All kinds of goodness up there. It looks like is running the CodePlex engine (and it probably is) but without a lot of the functionality of CodePlex.  Of course, it has a different goal and purpose. CodePlex is for complete projects and provides a collaborative environment for developers to build Open Source applications. Code Gallery, however, just has code snippets and other useful stuff that you can add to your projects.

So ... this resource that I created ... it's not published yet, so you can't find it. However ... I will be adding code samples from this blog up there so that you can download them easily for inclusion in your projects. When I get that done ... and that should be in the next week or two ... I'll post the link to it here and will also have a link on links at the right.



Tags: ,

.NET Stuff | Idle Babbling

A little trip down Memory Lane

February 20, 2008 11:41 PM

Every once in a while, something comes up that gets me reflecting on where I've seen computing come from ... and my experiences with it. Certainly, I often talk to some of the "newer" folks in the IT community and feel like a grizzled old fart (think "I remember when ..."). I can just imagine what these stories will be like with my (hopeful) grandchildren hear them. 

So ... I started programming, believe it or not, on a Casio fx 7000-G (I'm amazed that it has a Wikipedia entry). I got it back in my freshman year of high school (it was new then) at a place across from my freshman high school, Calvert Hall, called "Best" (not Best Buy ... just "Best"). Best no longer exists; Calvert Hall still does. By sophomore year (no longer at Calvert Hall, but at Towson High), I was programming this little calculator to do my math problems for me. I don't think my teachers quite got what it was or what it did; it's not like there were many programmable calculators at the time. It wasn't until senior year (by now at Dulaney High) that I actually had a teacher that truly understood what this thing did. He was my physics teacher (I'll not mention his name, but he did talk a lot about his heifers) and he had no problem with it. His attitude was this: if I knew the equations well enough to program the calculator, then I knew them pretty well, which was the point. And this calculator was the reason that I had a 110 average one semester ... not only did I ace all the tests (duh!) but I also wrote a bunch of programs for him to use in his Casio fx 7000 that he gave me extra credit for. He had no idea how to do it and, by this time, I could make that little thing with all its 422 bytes really hum.

But, of course, let's not forget the consoles.  I first saw one when I was  somewhere around 8 or 9 (it was before my adopted sister, Nickkie, came along) at my Aunt Toni's place. It had Pong. That was all. I played it all night. I can't remember when we got an Atari 2600 console, but I do remember spending hours on it. But the cool one that I really wanted was the Intellivision with Intellivoice ... a friend Kevin and I would play B-17 Bomber at the Hecht's demo station for hours after walking the 20 minutes to get there. But neither his parents or mine actually got us the unit, much to our dismay.

As for "real" computers (as in PC's), my first exposure was at a friend's house in the neighborhood, Karl. His dad was a principal, so they got an Apple ][ and then an Apple IIC either cheap or free (I'm not sure which). He was, at the time, much harder-core than I was and had actually had written some (simple) code on it. He even had 2 floppy drives!! This was before high school, if I remember correctly. My exposure was limited to playing the original Castle Wolfenstein (complete with yells of "Schweinhunt!") and Crusade In Europe. I thought it was cool and we'd spend hours on end playing it (it replaced AD&D as a favorite way to spend the summer -- between the 2 of us, we had all of the books for AD&D). Another friend (JP and Chris) had the Atari system (I forget ... and can't find ... which ... it wasn't the Atari 800) that had a keyboard and dot matrix printer (wow!) with word processing software. We did a neighborhood newsletter on it ... I was the editor. I think there were 2 editions before we got bored with it. For high school. Calvert Hall was actually very progressive ... they had a computer lab with Apple ]['s.  I played Oregon Trail when I wasn't getting into trouble. Then, at Dulaney, I took drafting in junior year and we got the very first Apple Mac's in the county to do some simple CAD. Well, we got the first one. We had one for the whole class and we had turns to do some simple CAD assignments in between doing drafting the hard way (with pencils, that is). I think I still remember how to use a T-square and triangles ... and how to align the drafting paper to the desk and tape it down. That wasn't even analog, folks. I didn't have a computer myself, though. Parents never saw fit to get one and, by the time I was half-way through my senior year of high school I was "emancipated" and struggling just to eat something besides chicken hot dogs and Ramen noodles. It was, to be sure, interesting to explain to the school administration why I was under 18 and writing my own absence notes but, I have to say, there were some great teachers and counselors (Mrs. Kirchner and Mr. Fanto jump to mind) there that believed in me and really helped. That said, I wrote my senior paper at my girlfriend's (Laura) house on WordPerfect v.(I have no clue) since I didn't have a typewriter.  In my first 2 years of college (at Essex Community College, now a part of the Community College of Baltimore County), I took an "Introduction to Computers" course where I learned all about DOS, WordPerfect, Lotus 1-2-3 and dBase. Somewhere in that time, I bought myself a "Personal Word Processor" on my Circuit City credit card ... I guess you can call it a computer of sorts ... to write my papers (very important for a lit major/philosophy minor). It was fun to change the disks for regular and italic. But bold didn't exist. I had a lot of my poetry and short stories on those disks, which are now lost forever. But, by my second year at ECC, I was doing most of my papers at my girlfriend's (Michelle) house ... her parents had a PC with WordPerfect.

With that background, I'll move forward into the "J has a computer" era. On graduation with my Associate's Degree, I got my very first computer. It was an AMD-based 386sx25 with an 80MB hard drive, 3 1/2 and 5 1/4 floppy drives, a whole 2 MB of RAM and even Windows 3.1! Remember MemMaker? I was set, now, for my entrance into Goucher College. It was there that I took my first computer programming class ... on QuickBasic ... and got started down my current path. I was, however, still an English lit major. Through that time, I only had one professor that actually "got" computers ... he'd take papers by email (hi tech stuff at the time) and also introduced me to Neil Stephenson's Snow Crash. Of course, I was, I guess, the only student in his classes that got computers in a pretty hard-core way and we'd talk about the possibilities of HyperCard to create reader-driven literary experience that could only exist in the digital world. This was, ironically, the same prof that I had for my Chaucer class. I was, at the time, very interested and heavily influenced by the Reader-response critical theories (I wanted to study under Stanley Fish for my post-grad) and this was a natural extension of it. I also finally had Internet connectivity from my home. With a 1200 baud (that's bits per second for you young 'uns out there) connecting to a Unix host server running all text-based applications. Like Pine, Lynx, some Gopher client (Gopher was cool back then). The UseNet was actually usable.

I built my first computer shortly afterwards. It was a 486DX2/50 with 8 MB RAM. It had VL-BUS for the graphics card, which were just beginning to be something more than a stupid thing to push graphics to the screen. I had a Hercules VL-Bus card, though I can't remember the name of it. Oh, yeah, and sometime around then, hard drive storage got down to $1/MB. I bought a 350 MB HDD for $345 and thought I had a vast expanse of hard drive space that I'd have a hard time filling. There was also the EISA architecture out there for add-on cards, but it was too expensive. PCI finally killed it off completely. Now, to get all the parts, I didn't go online. Ecommerce didn't exist then. I don't think that Mosaic had been released yet. I used a magazine call Computer Shopper and browsed through all the ads, calling my orders over the phone (how quaint!) Wolfenstein 3D was out too, and much better than the original Wolfenstein. And let's not forget Doom. Even better, though, I absolutely loved Descent and would actually play a friend over the modem. I'd also upgraded my modem to 2400 baud, then 9600. Eventually, internet connectivity was via a dial-up interface more similar to what we have today (for modems, that is), but configuring it was something of a nightmare. WinSock was a pain to do and get SLIP configured correctly was also a lot of fun. And then standing in line for Windows 95, buying it at midnight ... wow. 

It's amazing to look back where all this technology started. In just a few short years, we now have multi-core processors easily available. For the longest time I wanted a dual-CPU system, but it was just too expensive. Now you can get 4 cores on 1 chip (I don't have one of them ... yet). Gaming has gone to new levels on both the console side (XBox 360) and the PC side. Memory? I've got 4 GB. That's bigger than a lot of the hard drives that I've owned. As for hard drive space, my data drive is 1TB. My OS drive is 750GB (for multi-boot). That's almost 2TB on one desktop. High speed internet connections are pretty standard fare ... and you can even get cellular high-speed internet adapters for your PC, so you can have broadband just about anywhere you go. My phone is probably more powerful than my first computer. It's certainly got more memory. And graphics cards? Well, the GPU's are faster than many, if not most, of the computers I've owned and they have more memory than you could even put on a motherboard until recently. These are dumb cards anymore, not by any stretch of the imagination.

What will things be like 15 years from now? My mind spins just thinking about it. But ... I have no doubt that we'll look back on today's computing platforms and laugh at how powerful we thought they were.



Tags:

Idle Babbling

Hashing in .Net

February 13, 2008 2:35 PM

I've talked about DPAPI and symmetric encryption. Both of these are very good for certain things. But what about passwords? Encrypting them with DPAPI is not ideal ... as DPAPI from ASP.NET would be machine-specific; it won't scale out and it's not easy to transfer between machines if there is a need for disaster recovery. Symmetric encryption can be a reasonable option, but there is a more secure (and faster) way to do this. Let me explain a bit further. Let's say that you forget your Windows domain password. Can you get that password back? No, you can only reset the password. Yes, I know there are password crackers, but they do tend to be brute-force tools or they use tables with known hashes and compare them to what's in the SAM. So, I'm sure you can guess what it is ... hash algorithms (yeah, I guess the title was a giveaway).

Hash algorithms have a simple function: the take input text, run it through and algorithm and produce output that cannot be reversed to the original. A small change in the input results in a large change in the output. The output itself will always have the same size, in bits, regardless of the input. So, for example, a 500 character string processed by a 256 bit hash algorithm will always return a 256 bit value.  As would a 1 character string. This is another key difference between hashing and encryption functions. However, the same input will produce the same output ... so it is, as you can certainly guess, a very good way to store passwords. Since it's not reversible, it is very hard, if not impossible, for it to be retrieved except through a brute-force attack. And there are ways to make even a brute force attack even more difficult than they already are; we will touch on that. Hashes can be used for checksums (you'll see MD5 hashes used for checksums on many Linux distribution downloads) ... they can be considered a "digital fingerprint" that ensures the integrity of a downloaded file, zip archive and more; however, there are other algorithms that can also be used for these purposes that are not secure (for example: CRC or cyclic redundancy check).  All of the hash algorithms in .Net inherit from System.Security.Cryptography.HashAlgorithm.  And, of course, you can find them in the System.Security.Cryptography namespace.

Hash Algorithms Supported in .Net

  • MD5: This is a widely used 128-bit hash algorithm, especially for validating downloaded files. It is an Internet standard, being described in RFC 1321. However, there are known issues with MD5, with collisions (that is, two different inputs producing the same hash) being having been shown to be found on a laptop computer in a minute. While there are ways to mitigate this, in general it is not recommended for new applications.
  • RipeMD160: This is a 160-bit hash algorithm designed to replace the earlier RipeMD, which was, in turn, based on the now-defunct MD4 (which was replaced by MD5). Like MD4, the original RipeMD was found to have some weaknesses.  RipeMD 160 improves on this, if only because the size is larger.
  • SHA1: Designed by the National Security Agency for use as a Federal Information Publishing Standard (FIPS). This produces a 160-bit hash value. It is in the process of being phased out due to vulnerabilities that have been reported in the algorithm.
  • SHA256, SHA384, SHA512: This family of algorithms is collectively known as SHA2. They have lengths of 256, 294 and 512 bits, respectively. Due to the known issues with SHA1, these algorithms are generally considered more secure.

OK, so we have that out of the way. So, let me run something else by you. Remember when I said that the same input produces the same output? That can be problematic, especially with passwords. This is because if you know that one password is, for example P@ssw0rd and see that another entry has the same hash value, then you will know that the second entry is also P@ssw0rd. Symmetric cryptography has a similar issue and, with symmetric crypto, we use an initialization vector to resolve it. But hash algorithms don't have an IV. Instead, with a hash algorithm, we use a salt. This salt is the extra bit of gobbledygook that provide the randomization required to ensure that the above scenario doesn't occur. As with an initialization vector, this can be stored in the clear. But ... it's something that you have to add to the data to be hashed; there are no properties for it as there are with an IV.

And now, without further ado, for some code. A note ... I'm passing the name of the algorithm into the function. This isn't necessary, but it does provide some flexibility. You can use the names of the algorithm (above) or you can hard-code the algorithm's class into the function.

This first code sample shows hashing in its simplest form ... no salt, nothing special, just a straight hash. The return value is a Base64 Encoded string ... I do like to use these for better (and easier) storage at the database level, though it is at the expense of some CPU cycles on the application logic level.

private string HashPasswordSimple(string password, string hashAlg)
{
    //convert the password to bytes with UTF8 Encoding. 
    byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(password);
    //HashAlgorithm is disposable, so we'll use a "using" block
    using (HashAlgorithm hashAlgorithm = HashAlgorithm.Create(hashAlg))
    {
        byte[] passwordHash = hashAlgorithm.ComputeHash(passwordBytes);
        //convert the computed hash to a string representation ... 
    string hashString = System.Convert.ToBase64String(passwordHash);
    return hashString;
    }
    
}

As you can see, there's not that much to it. Pretty straightforward. To verify a password, you recalculate the password's hash and then compare it to the stored value. Adding a salt takes this up a level and, of course, you'll need to the salt somewhere as well. Good thing is that the salt isn't helpful by itself to a bad guy, so you can store it in the clear. Here is one method of using a salt (you can also add it to the end, etc. just a long as you can reproduce it).

private static string HashPasswordSalt(string password, byte[] salt, string hashAlg)
{
    //convert the password to bytes with UTF8 Encoding. 
    byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(password);
    //Add the hash to the password bytes. 
    byte[] hashData = new byte[passwordBytes.Length + salt.Length];
    //Use Buffer.BlockCopy to copy the salt and password
    //into a new array that will actually be hashed.
    Buffer.BlockCopy(salt, 0, hashData, 0, salt.Length);
    Buffer.BlockCopy(passwordBytes, 0, hashData, salt.Length, passwordBytes.Length);

    //From here, compute the hash.  
    //HashAlgorithm is disposable, so we'll use a "using" block
    using (HashAlgorithm hashAlgorithm = HashAlgorithm.Create(hashAlg))
    {
        byte[] passwordHash = hashAlgorithm.ComputeHash(hashData);
        //convert the computed hash to a string representation ... 
        string hashString = System.Convert.ToBase64String(passwordHash);
        return hashString;
    }

}

The next question, of course, is how to create the salt. There are many ways to go about it as long as it is unique to the individual hash (i.e. the same passwords should not have the same salt ... would defeat the purpose). You can use the System.Security.Cryptography.RandomNumberGenerator class to create the salt. This class generates a cryptographically strong random sequence of values ... just using the System.Random class doesn't do that. You can use a unique identifier associated with the user account (for example) to create the salt ... i.e a user id Guid. You can do any number of things as long as it is unique in the hashing context.

In addition to traditional hash algorithms, .Net also has support for keyed hash algorithms.  These take regular hashes a step up and are more commonly called a Hash Message Authentication Code (HMAC).  These algorithms use a hash algorithm in addition to a secret key. This provides not just the data integrity, but also the integrity of the message. Think about it for a second ... if a hash algorithm is repeatable, a hacker could intercept the message, change it, recalculate the hash and you'd be none the wiser. With an HMAC, this is not possible as the key is required to regenerate the hash. A keyed hash algorithm is essential to protect the integrity of a hash value that is transmitted to users (for example, in ASP.NET's ViewState). Keep in mind, however, that you still need to think about protecting the key. With all of that said, .Net does support 2 keyed hash algorithms and they both inherit from System.Security.Cryptography.KeyedHashAlgorithm.  This, of course, inherits from HashAlgorithm.

Keyed Hash Algorithms Supported in .Net

  • HMACSHA1: Based on the SHA1 hashing algorithm (and, therefore 160 bits), this adds a key of arbitrary length to the function.
  • MACTripleDES: As it's name implies, that uses the TripleDES algorithm to produce a hash. The keys can be 8, 16 or 24 bytes and generates a 64-bit hash.

The only difference between a straight hash algorithm and a keyed hash algorithm is the addition of the key. There isn't a need for a salt with a keyed algorithm; it is used for a different purpose (message authentication and validation) than a regular hash algorithm and, since the HMAC is authentication a message sent in the clear, there really isn't any point to it. An example of using a Keyed Hash Algorithm is in ASP.NET ... the <pages> element has an attribute of "enableViewStateMac".  This has nothing to do with enabling ViewState on Macintosh, but to add a MAC to the ViewState. There is also a page directive that will do this at the page level. The key used can be specified in the <machineKey>; if you have it auto-generated, you run the chance that the ViewState will fail validation when the AppDomain recycles or, if you are using a web farm, the request goes to another web server.

That's all for now. Have fun and happy coding!



Tags: , ,

.NET Stuff | Security