Archive for February, 2007
Wednesday, February 28th, 2007
Michael and Raymond introduce Update Controls .NET, then dive into the concept of abstraction. An abstraction hides details so that you can solve problems at a higher level. A good abstraction hides the accidental complexity of the problem space, and reveals only the essential complexity of the solution. Abstraction is a key concept in the construction of Software Factories, which create abstractions within problem domains.
Sunday, February 25th, 2007
I am pleased to announce the release of a new product line and web site. Update Controls .NET is a suite of Windows Forms controls that automatically update themselves. A short demonstration loop is up on the main page right now, and more detailed videos will be posted within the next few weeks.
In traditional Windows Forms programming, you have to set properties on the controls in order to populate them with data. When the data changes, you have to set those properties again. Usually, you will end up writing one method that sets all of the control properties whether they need it or not, and call that method anytime something happens.
With Update Controls, you don't set properties. Instead, you handle events that get and set the data. For example, the UpdateTextBox control fires GetText whenever its text is out-of-date. You handle that event and return the text that it should display. When the underlying data changes, the control fired the event again.
It may seem like magic, but it's really quite simple. You put Dynamic sentries in your data objects that keep track of each time your properties are accessed. Whenever a property is accessed during the course of a GetText event, that control's text is linked to that property. When the property changes, the control is out-of-date.
Go download the library and try it for yourself. Most people who have tried it can't bring themselves to write Windows Forms without it.
Wednesday, February 21st, 2007
Anecdotes and stories from experience, and the lessons we've learned from them:
- Deploy changes to a database and application simultaneously.
- Define and stick to your process.
- Don't forget your where clause!
- Have a successful code review.
- Manage dependencies.
- Put a stop to scope creep.
- Be agile ... but not too agile.
- Think it through.
- Don't stifle creativity.
- Use patterns wisely.
- Avoid tight coupling, especially inheritance.
- Fear financial applications.
Thursday, February 15th, 2007
We all have experienced the main problem with passwords on the net today: every site we visit demands that we create one. To be secure, we have to generate a different password for each site. To stay sane, we have to find some way to avoid memorizing them all. My last post provided a secure solution to that problem, but the password system is still flawed.
After the multiple password problem, the next big dilemma is phishing. A nice side-effect of using a secure password cache like a TrueCrypt/Portable Firefox key is that the cache is not fooled by phishing attacks. An attacker cannot fake an SSL URL, so Firefox will not enter your password for you. Since you have created a separate password for each site (you did, right?), and since you haven't memorized any of them, you can't enter your own password yourself. But most people don't go through the trouble of creating a secure portable password cache, so they might still fall for it.
The latest trend is to use SiteKeys to prove that the web site is who they say they are. When you sign up for your on-line banking account, you choose a picture from their list. An attacker wouldn't know which picture you chose, so they can't display the SiteKey to you during a phishing attack. So you only enter your password if you see the key.
That's the theory, anyway. According to one study, many people don't understand the SiteKey idea, and will enter passwords even without that visual verification. But even if people were well-behaved, SiteKey is vulnerable to a man-in-the-middle attack.
In order for the bank you know which SiteKey to show you, you musts first enter your username. So suppose a phisher duplicated this UI and collected your username first. They could then forward your username to the bank and scrape your SiteKey off of their login page. They display it to you, you enter your password, and they have access to your account.
The crux of the problem is that both SiteKeys and passwords are shared secrets. Both parties know the secrets fully. It's like the secret code phrases that fictional spys use to authenticate one another. But if both parties know the secrets, then a middle-man can listen in as they exchange them. The best solution is a private key system.
SSL is not vulnerable to man-in-the-middle attacks because the host site has a private key that it does not share with anyone else. To verify the correctness of the key, a visitor obtains the matching public key from a trusted third party. A random challenge is encrypted with the public key, and only the holder of the private key can decrypt it. So if there were a man-in-the-middle, he could not correctly respond to the challenge.
The only way this can work is to be able to prove that you have the private key without showing it. If we were to apply this to humans, that means that we would have to memorize a large number and do math in our heads in order to securely log into a website. Talk about loosing your sanity.
The next best thing is to have a device that stores the private key AND performs the calculations on your behalf. If the device just stores the key, then an attacker could get in between the calculator and the device in order to steal the key. That is the weakness of the TrueCrypt/Portable Firefox solution: if you put your thumb drive into an untrusted computer, it could be using a key logger to get your TrueCrypt password. Or it could be reading the encrypted volume after it has been mounted.
Here's my solution
I want a USB device with three things: memory to store private keys, a processor to run encryption algorithms, and a key pad to capture my (one and only) password. If I had this device, I would be confident that no one could get in the middle to steal my identity. It could establish SSL connections to all of my websites so that nothing running on the host computer could spy on sensitive data. Of course, the host computer has to be able to render the web page, but a well-designed page is not going to expose private information.
Tuesday, February 13th, 2007
The ideas of identity, mementos, and database design come together in a technique known as Object-Relational Mapping (ORM). While ORM frameworks cut initial development time, they do come at a price. Should you invest in a framework, or do it all yourself?
Hybernate, an ORM framework for Java and .NET
Fowler, Martin; David Rice, Matthew Foemmel, Edward Hieatt, Robert Mee, and Randy Stafford (November 2002). Patterns of Enterprise Application Architecture. Addison-Wesley. ISBN 0-321-12742-0.
Thursday, February 8th, 2007
If you sign on to a new website at work, you can ask your browser to remember the password. But that doesn't do you any good when you get home. And, that password is available and visible to anyone else who logs on to your work machine. Fortunately, you can secure your password cache and take it with you.
First you will need to get a USB thumb drive. You don't need a "secure key", since you will be adding the security software yourself. A large drive is not necessary either. I use a 32 MB drive that I got from the impulse lane of the grocery store, though it is a tight fit.
Second, download TrueCrypt. You don't even need to install the software on your PC. Just open the zip file and run TrueCrypt.exe from the "Setup Files" folder. Click "Create Volume", "Create a standard TrueCrypt volume", Next. Assuming your USB drive is "D:", enter "D:\portable.tc" and click "Next". Choose your encryption and hashing algorithms (I like AES and SHA-1) and hit "Next". Enter a volume size saving at least 1 MB for TrueCrypt (so my 32 MB jump drive has a 31 MB volume on it) and hit "Next". Now enter and confirm a password and hit "Next". (Do not use keyfiles for this procedure, and do not click "display password".) Now move your mouse over the dialog a few times to seed the random pool and hit "Format". When it's done, hit "Exit".
Third, install TrueCrypt on the USB drive. You should be back to the TrueCrypt window, so open the "Tools" menu and choose "Traveler Disk Setup". Again assuming your jump drive is on "D:", enter the root drive "D:". Uncheck "Include TrueCrypt Volume Creation Wizard" to keep TrueCrypt under 1 MB. Choose the option "Auto-mount TrueCrypt volume (specified below)". Then enter "portable.tc" without the drive letter or slash. Then click "Create", click "OK" on the popup, then click "Cancel" to close the traveler disk setup wizard.
Fourth, mount the encrypted volume. The easiest way to do this is to safely remove the USB drive (first using the "Safely Remove Hardware" icon in the system tray) and reinsert it. Alternatively, you can open "My Computer", right click on the drive, and select "TrueCrypt Mount". You will be prompted for your password.
Fifth, install Portable Firefox on the encrypted volume. Download the installer to your hard drive, run it, and enter the drive letter of the mounted encrypted volume (for example "E:").
For convenience, you may want to create a batch file on the root of your encrypted volume. Create a file called "Firefox.bat" containing the line "FirefoxPortable\FirefoxPortable.exe". Since you don't know what drive letter will be assigned, you have to use a batch file instead of a shortcut. This will allow you to double-click the batch file once you mount the drive, instead of drilling into the folder to double-click the exe.
To unmount the drive, right-click on the USB drive in My Computer ("D:" in this example, not "E:") and select "TrueCrypt Dismount All". Then use the system icon to safely remove the drive.
Now launch Firefox and start browsing. Go ahead and tell Firefox to remember all your passwords, safe in the knowledge that they are being cached to an encrypted volume. Take it with you to log in from any machine. You will leave no traces behind, and if your USB drive is lost or stolen no one can use it to get to your passwords.
Wednesday, February 7th, 2007
MySQL AB :: An Introduction to Database Normalization
A good description of database normalization to third normal form.
Thursday, February 1st, 2007
I use iTunes to subscribe to and sync my podcasts. I organize my podcasts in a playlist so that I can listen to them on my daily commute. This works very well in the car, as I don't have to take my attention from the road to find the next episode to play. However, the experience at the computer is not as good as it could be.
The Podcast section of iTunes contains a list of all my subscriptions. I start iTunes every morning, flip to the Podcast section, and hit the "Refresh" button. (Why iTunes doesn't install as a service and download my shows while I'm sleeping is a question for another post.) First it checks all of my subscriptions for new episodes. As it finds them, it displays the episode name and queues up the download. Before the download completes, the episode name is grayed out.
My goal is to choose the shows I want to listen to that day and drop them into the playlist in my chosen order. However, I can't do that until the download completes. So instead I have to leave the computer, eat breakfast, and return only after all the queued shows have (hopefully) downloaded. It would be much better to get it all done at once.
Here's my solution
An iTunes playlist is not a collection of content. It is a collection of references -- identities. iTunes already knows the identity of the podcast episode before it downloads. It can display the name, it can request the content from the remote server, and it can track the download status. All of these things require that it has a concept of identity for the show. It should be possible to drag an episode to the playlist before it finishes downloading.
iTunes has recently added a page that displays the download queue. This is a fantastic feature. But again, you cannot drag a podcast from this view into a playlist, even though this view is little more than a list of identities.
Fellow programmers, how can we learn from this oversight? When designing our applications we should be aware of the difference between an object and its identity. If we are loading a list from the database to display to the user, it is necessary to load all of the content, or is the identity sufficient? If we are attaching a document to a message, do we really need to copy the entire file or can we just include a universal path? Identity awareness is one of those little things that leads to a better user experience.