Android Development, Part 1: Project Structure and Tools
posted on 09/01/10 at 08:13:55 am by Joel Ross
This is the first part of an ongoing series about my adventures in building my first (non-trivial) Android application. For more information about the application, you should peruse my series introduction.
I still don't plan to show any code yet, so I guess you can still consider this an introduction to the application. I feel it's important to talk about the tools and frameworks I'm using, and then talk about how I'm structuring my application.
First, the tools and libraries I'm using:
- Eclipse and the Android SDK: Just about every tutorial lists Eclipse as the editor, and for good reason. There's some nice features there, including a lot of nice refactorings. It's not quite as good as Resharper and Visual Studio, and I still fumble my way around a bit, but it gets the job done.
- Instinct: This is a BDD framework based on jMock that John Sonmez showed me. It doesn't use the AAA syntax that I'm used to, but it works and allows me to test code in roughly the same way that I'm used to. This uses jUnit to run the tests, which works well, since Eclipse has nice integration to run jUnit tests directly in the UI.
- Roboguice: Back when I spent more time in IRC, I remember Nate Kohari talking about how he based Ninject on Guice, a IoC container in the Java world. Well, Roboguice is essentially Guice, but with a few additions that make it easier to work with Android-specific objects. Since I work with Ninject on a daily basis, going with this just made sense.
- kSoap2: I'm communicating with existing SOAP web services from the Pay It Square site, so I'm using a fork of kSoap2 specifically compiled for Android.
We're considering moving to a more REST-based interface for our web services, and if that happens, we'll swap out kSoap2 for something else. I've also thought about moving to using json for data transportation instead of XML, but that's down the road as well. V1 is top priority right now, and XML and SOAP work fine for now, as long as I properly insulate their usage.
I've been asked if I'm going to be using MonoDroid to build this application. The short answer is no. The slightly longer answer is that when I started building the application, I wasn't yet in the MonoDroid beta program (I am now), and I wanted to get a feel for what it's like to build for the Android platform using the toolset Google recommends. It's the same reason I would probably go with Objective C if/when we build an app for iPhone. I will definitely be exercising MonoDroid, but not for this, at least not right now.
On to project structure. Right now, I have three projects. First, I have my UI project, which contains all of my Activities, layout files, resources, and my application manifest. It's the only project that actually has a reference to the Android library.
Next, I have my core library. I'm using the MVP pattern, and this project contains all of my presenters. It contains any of my services, repositories and domain objects as well. It also has a series of interfaces I've created that wrap functionality in the Android libraries. I've done the work to create interfaces for all of the Android-specific functionality so that I can easily test the core library with my third project - my tests. Wrapping the interfaces gives me two things: 1.) It's testable, because I can't run Instinct's tests against any Android objects, and 2.) More importantly, it allows me define how my presenters will interact with the Android OS, rather than the other way around. That's not entirely true, but it sounds good, right?
Now that we've laid out the tools I'm using and the structure of my project, it's finally time to get into some code. In part 2, I'll get into the details of how I'm actually wiring up my presenters and activities.
Categories: Android
Android Development, Part 0 of N: Introduction
posted on 08/25/10 at 09:00:00 am by Joel Ross
I've spent the last few weeks building my first Android application. I wanted to get my feet wet, but watching videos and reading about it just doesn't quite cut it for me, so I decided it was time to dive into a real application - the best way for me to learn. It took me a while, but I finally found an app worth building, so that's what I'm doing.
This is my first dip into the Java pool, so it's been a bit slow going - learning a new language (yes, it's very similar to C#, but different enough to trip me up every now and then), a new IDE, and a new environment. I've been doing mobile development at TrackAbout, but not for Android, so it's a bit different, although there are some similarities.
Anyway, I'm going to do a little series about Android development. No promise on how many articles it'll be or a schedule - just that since I'm going to be doing the development, I should write about my progress.
We'll start off with an overview of the application, so we're all on the same page and have an understanding of what will be built. I created a few mockup using Balsamiq Mockups, and while I'm sure the look will change, the functionality will be roughly the same. The application will be a mobile application for Pay It Square. For those not familiar with Pay It Square, it's a site that allows you to create collect pages so you can collect money from friends, do event registrations, or collect donations. We think allowing people to see and manage their collect pages on the go will be a great addition.
I didn't mock up all of the screens, but I have a few I'll share. The main screen will show you a list of your collect pages, along with a bit of information about each one, such as information about how many people have and haven't paid, how much each member owes, and how much you've collected so far. Once you select one of the collect pages, you're taken to a tabbed interface, where you can see a list of who's paid, who hasn't paid, and be able to add new payees. The screens are below.
For V1, we're mainly focusing on displaying information, rather than collecting it (with the exception of adding a payee). V2 will add more of that functionality, but we want to get something out the door soon, so we've limited scope to be able to accomplish that. The functionality required to implement these few screens (and a couple of others not shown) will be what I plan to cover in this series.
Categories: Android
What’s On My Phone
posted on 04/06/10 at 12:10:36 am by Joel Ross
I've been relatively quiet lately, and part of it's because I've been so busy with work and the NCAA tournament that I haven't had time. And in recent months, I've switched to be more a consumer of technology than a producer - in the form of a new phone. Well, not new, but relatively so. Back in November, I got a Motorola Droid - I actually got it the day it was released. I turned in my Touch Pro 2 (which I really liked) and moved to Android. It's not a move I've ever regretted.
Anyway, today, Dan Hounshell tweeted that he'd like to see a list of the apps I'm using on my phone, along with a promise to follow up with is own. I responded saying that sounded like a great idea - with the hope being that someone will point out an application that I'm missing.
I'll preface this by pointing out that I haven't purchased an app yet - every app listed is either free or the "light" version of a paid application. I'm not against paying for an app - it's just that I'm cheap, and I haven't found a key feature or app that's justified it.
So let's get started. The three apps I use the most are built-in: Mail, calendar and browser. I have 5 email accounts that I've added to my phone - my personal one (which is actually a consolidation of quite a few), my work one and three for Develomatic. They're all Google Apps accounts, so the integration is seamless. I've granted access to my work calendar from my personal Google account, and have various calendars for my personal account anyway, and they're all synced to my phone as well. I even have The Wife's calendar on my phone, so I no longer have to check the fridge to find out what's going on this weekend. The browser is also very sold, and I have a couple of bookmarks that I use all the time: Google Reader and Instapaper.
But that's not the real reason we're here, right? We're talking about what I've grabbed from the Marketplace. So let's get to it. I'll start with the apps on my home screen:
- Twidroid: From every review I've seen of twitter clients on Android, Twidroid is always number one. I tried a couple others early on, and none even came close.
- Google Maps: It's technically built in as well, but it's worth highlighting. It comes with free voice navigation which works very well. I love that it zooms in and out based on how fast I'm going.
- Foursquare: I don't use Foursquare like most people do, I don't think. I have no friends on it, and when I check in somewhere, it doesn't tweet that or post it to Facebook. But I still try to check in where ever I go. I used it extensively on our recent trip to Hawaii and have used it to remember a few places that we went to while we were there. I do find it a bit ironic that I'm the "mayor" of more places in Hawaii than in Michigan though!
- Bible from YouVersion.com: I like that they have quite a few reading plans and it syncs those plans between the web and my phone so I can remember where I am.
- CalWidget: While not technically an application, it does take up 1/2 of my main screen. The default calendar widget doesn't do it for me. This gives me a lot of customizations for what I want to show up from my calendar, what size I want it to be, and how I want it to look. Both The Wife and I use it and love it.
The Droid only has 3 screens. What's listed above covers the main screen. One of the other screens contains links to direct dial contacts - The Wife (both home and mobile), parents, friends, etc. I also have the "Power Control" widget so I can quickly turn on and off wireless and Bluetooth.
The last screen contains programs I use often, but not all the time.
- Games Folder
- ThrottleCopter: Such a simple game, but it's addicting. Basically, you press the screen, the copter goes up. Release and it goes down, and your goal is not to hit the top or bottom of the cave.
- Robo Defense: I haven't played this in a while because it's too addicting. I played quite a few games over the course of a couple of weeks, and realized I was wasting 30-45 minutes at a time. Still, I love the tower defense type games.
- Flight Director: This is probably my favorite game I have. Planes come on the screen and you use your finger to draw a path to the runway. Your goal? Land as many planes as you can without any crashing.
- Toss It: Another simple game. Take a balled up piece of paper and "toss" it into a trash can while a fan is blowing at different speeds. I think it would be a lot cooler if it used the accelerometer, but it's still something that you can play for to kill a few minutes.
- ShopSavvy: Two weeks after I got my Droid, my garbage disposal decided that leaking water into the area where the power connected would be a good idea. After numerous blown circuits, I headed to Home Depot to get a replacement. I found a 1/2 HP replacement. On a whim, I scanned it with ShopSavvy and found it online for 1/2 the price, and realized it's reviews were awful. As a result, I bought a 1 HP garbage disposal that was highly rated for the same price. Yeah, ShopSavvy is a keeper.
- KeePassDroid: I've use KeePass to save all of my passwords on my laptop/desktop for years. Being able to access that same info on my phone is nice, although I do wish that it supported the 2.x file format, but alas, I'm stuck on 1.x for now.
- Pandora: I work from home, so I use my desktop machine to play music most of the time, but the combo of my Droid and the AUX input on my car stereo is killer.
- Facebook: The Android Facebook app is pretty weak. I don't use this a lot other than for its ability to sync Facebook contacts with my phone contacts. If I want to go to Facebook, I'll just go to their mobile interface (not m.facebook.com though - touch.facebook.com is a far better experience).
- Key Ring: This stores all of the store shopping cards in my phone so I don't have to carry them. Sounds great, except a lot of scanners don't work well with the shiny screen on the Droid. But for the ones that work, it's great!
- Aldiko: I haven't found a book reader that I love (Amazon, where are you?) but Aldiko is best I've found. It's slow, but it allows me to read an ebook on the go.
- TripIt: I use this rarely, since I don't travel like I used to, but when I do travel, it's nice to have all of my travel plans handy.
- Fring: IM and Skype on my phone. Not sure I really want to have IM capabilities on my phone, but at times it does come in handy.
- Google Voice: I don't use this to it's full extent mainly because I don't want to go through the hassle of telling everyone I know I have a new number. But I do give out my Voice number any time I have to fill out a phone number online or call someone that I really don't want to have my number.
- Evernote: I use this mainly for reading notes I've taken on my desktop, but it's nice to have the option to take notes if I have to.
Those are the main applications that I use. I have others installed, and while they're decent applications, they're just not ones I use all the time:
- AppBrain: I like the idea here. Install this, and then go to their website. You can search the market place and select apps to install and they get installed on your phone. And it keeps track of the apps you have installed for you online. This seems like the perfect thing to have if I ever needed to swap out my phone for another one.
- Gesture Search: Google released this and it's pretty cool. I just don't think to open it. It seems to me that this belongs as part of the OS rather than an app living in isolation.
- PapiRiver: I'm a sucker for games that use the accelerometer. This is one that does.
- Read Later: This isn't really an application. It provides an option for the browser's "Share" menu to save the current URL to Instapaper, which I use all the time.
- Skype mobile: The official Skype app on Android. It only works over 3G, which seems a little odd to me, but whatever. It works good in test. I'll have to try doing our daily stand up meeting one day.
- TasKiller: I use this rarely, but every now and then, I use it to kill an app. Simple, but effective.
- The Weather Channel: This one ends up living in the Notification area and I can always see the current temp where I'm at. It also shows me any warnings in the area by turning red. It's one I end up using all the time, but never really think about the fact that I'm using it.
I linked a few of the apps, but for the rest, they either don't have a dedicated web page, or it's just easier to search in the Android Marketplace.
There are a few things that I'm missing though and would really, really like to see:
- DropBox: I already use Dropbox to sync my Keepass password file between different machines. I'd like to have it automatically do that on my phone too. It's coming, but I want it now!
- Kindle App: I recently turned 3G on my Kindle on long enough to sync where I was in a book between it and my desktop (because The Wife keeps stealing the Kindle!). If there was a version of the Kindle software for Android, I'd leave it on permanantly.
- Instapaper: Yeah, the mobile web page is nice, but I'd really like to see a native application. The author of Instapaper states he has no plans for this, because he doesn't have time. That's unfortunate. What's more unfortunate is that the API doesn't allow you to build your own. Maybe someday.
That's what's on my phone. What's on yours? What am I missing?
Categories: Software
The 3rd Annual RossCode.com March Madness Pool
posted on 03/16/10 at 12:29:59 am by Joel Ross
I'd like to interrupt this blogging drought to let you know that I'm running the 3rd annual RossCode.com March Madness Pool Contest, and I want you to enter!
There's no prize, but if you can pick better than anyone else, you'll de-throne my uncle, who won last year's pool. And if you do enter, you can add your entry into the main pool (you'll see how after you submit your pick to mine) and have a chance to win a Best Buy gift card.
If you're reading this and thinking, "There's no point in entering. I don't know anything about basketball." don't worry about it. I've heard countless stories of people who won a pool by picking teams by uniform colors! So what's stopping you? Submit your picks now!
Categories: Just For Fun
Windows Home Server Saves The Day
posted on 01/04/10 at 09:49:59 pm by Joel Ross
On November 11th, The Wife's laptop needed to be rebooted. But it didn't turn out to be a normal reboot. Why? Because it wouldn't complete that reboot for nearly two months.
It hung while rebooting. It wouldn't repair the OS install. It wouldn't come up in safe mode. It just wouldn't come up at all. Oh, it would get half way. But it wouldn't ever finish. After running a few diagnostic tests, it turns out the hard drive was bad. It was under warranty, but that's where things got.interesting. We bought it at Circuit City before they went out of business. It's a long drawn out story which I'll leave out, but I will say this: Circuit City warranties are serviced by the same company that Radio Shack uses. As a result, I'll never buy anything that's covered by a warranty from The Shack. It was an all around horrible experience.
But, we did finally get it back - on January 3rd. I wasn't worried about any data on the drive, and it came back with a fresh Vista install (which is odd, since it originally came with XP!). I booted it up long enough to see that it worked, and then immediately took it into The Dungeon. I shut it down, threw in the WHS recovery CD, and booted it up. 3 minutes later, the restore was running.
Most people say it takes 15-20 minutes to restore an image. I didn't see that, and I was connected via a 1 Gigabit connection. It took a little over 5 hours total. And you know what? I'm OK with that. Sure, 15 minutes would have been nice, but frankly, it's still a TON better than loading all of the software by hand and then restoring all of the data manually.
This is the second time that my home server has saved me - the first time was just days after getting it, and I got a virus on one of my machines. It was going to be painful to get it off, so I just restored the latest backup. But this is the first hard drive failure that I've experienced since getting my WHS. I knew in theory it should be this easy, but I'm glad to see it actually work (you know, other than the whole "losing a hard drive and waiting 2 months to get it fixed" part).
And more importantly, The Wife is extremely happy. Talk about a WAF builder!
Tags: WHS | Windows Home Server | backup
Categories: Personal, Software
Trying Out Personal Kanban (Or At Least My Interpretation Of It)
posted on 11/09/09 at 11:02:31 pm by Joel Ross
One of the biggest things I struggle with is a way to manage what I need to do. I do a pretty good job of that at work, but in my personal life, things tend to get dropped. And at work, I feel that the amount of overhead I spend tracking what I need to do is too cumbersome. I've tried many different methods to track this stuff over time: Tasks in Outlook. Tasks in Gmail. To do list applications. Remember The Milk. A Todo.txt file. A personal Wiki. Evernote. One Note. Email. I even tried Paper once (that didn't end well. I can't read my own handwriting!). I'm sure there are others too.
How did that work out? Well, none stuck, so now I have tasks and notes about tasks all over my hard drive, notebooks, and spread throughout the Internet. Not exactly ideal, that's for sure. And because I tried new methods all the time, finding details about those items was tough, because I had to remember what the tool of the month (week!?) was when I was working on that particular item.
About a month ago, I saw a tweet from Joey Beninghove about PersonalKanban.com. That prompted me to read just about everything on that site. And it really got me thinking about how I could use this. I considered using an actual board, but ultimately decided to go with an online solution, since I wanted to be able to use this for more than just what I'm doing while I'm in The Dungeon.
The best online solution? Zen! It's a great Kanban solution built by Nate Kohari (author of Ninject) and his wife, Nicole. They've done an awesome job with the site. Adding tasks is about as frictionless as you can get, and moving them around is as simple as dragging them around.
The first step for me was to determine what stages my work goes through. In a typical project, these would be things like Backlog, Needs Defining, Ready to Build, Building, Testing, Waiting Deployment, etc. But for a personal board (at least for me), it felt more natural to define my stages as rough timeframes. After thinking about it for a while, I eventually settled on a set of "swim lanes".
- Far: This is my backlog. I could have left it as back log, but I felt Far fit better with my naming. This is where the whole universe of everything I need to do is stored. If I'm talking to my wife about something I need to do next Spring, I put it in here. If my boss says I should do something in a couple of months, I throw it in here. This way, it's tracked, and I don't have to remember it. It basically holds tasks that are more than a month away or I haven't had a chance to prioritize. I'll talk about how tasks get moved out of here later.
- Near: This is for tasks that I expect to start working on within the next month. By the time the task gets to this point, it should be fairly well defined. Any last details needed before work can begin should be figured out, and once it's ready, it gets marked as such. If it can't be defined, or it's waiting for another task to complete, I'll mark it as blocked so I know not to pull it forward.
- Here: Tasks in this lane are ones that could be done at any time - I expect that most tasks in this queue will be worked on in the next week. They should be defined and ready. If they aren't, there should be a reason - like it's due soon or it's blocked by something that's currently being worked on.
- Now: This is what I'm currently working on. It's fully ready, shouldn't be blocked, and just needs my focus to knock it out.
- Done: Once a task is done, it gets moved here, freeing me up to move onto another task.
- Archive: I have different criteria for how a task moves from Done to Archive, but basically, once a task is confirmed done, it gets archived.
So those are the steps my work goes through. It was nice to define that, but I didn't realize one of the biggest values of a Kanban board until I got everything entered and started using it for a little while. This screenshot illustrates it fairly well.
Can you see it? It has nothing to do with what the actual tasks are either. It's the visualization of my work. I use colors to tell me how tasks are categorized: orange ones are work tasks. Yellow are blogging activities. Teal are for Develomatic tasks, and blue are personal ones. I can, with a quick glance, get a good feel for what type of activity I need to focus my time on. I could never get that with any other task management applications.
So how does work go from one swim lane to another? It's a little different depending on what the task is for. Personal tasks are a bit different than work tasks, and Develomatic tasks are different than blogging activities, but the process is similar. I make a point to review the board on Sunday night, and get ready for the next week. This works out well, since at TrackAbout, our iterations are Monday through Friday. So tasks that I complete during the week get moved to Done, and on Sunday night (when we branch and update our staging site), I move the tasks completed in the last iteration to my archive. Personal tasks get Archived whenever I feel the job is done (read: The Wife tells me it's done!). Develomatic tasks get archived once it's been tested / deployed.
Any left over tasks that I'm still working on stay in the Now column. Since I don't usually have time for major personal tasks during the week, a lot times they'll get moved back to Here, or if I know I won't get to them the following weekend, back to Near. Any work in Here that I know I will do on Monday will get moved into Now, and any work that needs to get done the next week will get pulled from Near to Here. At that point, I check Far and look for things that are ready to be pulled out. If there's planning that needs to go into a task that I know will be coming up, I might create a task to handle the planning and drop that in Here. Basically, by the end of Sunday night, I like to have a rough plan for what my week will look like. Work tasks are usually the most up in the air because I don't totally control the priorities, but it's usually pretty stable for 2-3 days worth of work.
This review process happens a lot of nights, but Sunday is when I do a more thorough review and look into my backlog. Most of the other times it's simple a matter of moving more work into Now if I know I need more because something was completed that day.
For anyone familiar with Kanban, you'll notice one thing lacking on my board: WIP limits. That's work-in-progress limits, for those not familiar with Kanban, and the idea is that, in order to focus on the tasks at hand, you limit the amount of work you're doing at any stage, and you don't pull something else into that stage until there's a free spot. I haven't found a good balance here, and I think that's because of mixing different types of tasks. If I set a WIP limit of 2 for Now, and have two work tasks going, I have no room for anything else. While that may be just fine with my boss, I still have other commitments in other areas. So either I'm constantly moving tasks in and out based on what type of task I'm trying to do, or I do without hard limits. Moving them around all the time means more administration. Too much friction from the tool, and history tells me I'll eventually stop using it. So far, it's been a couple months and I haven't missed a day without checking my board. Ok, I may have missed a Saturday here or there, but that's about it. And I'd say I haven't been dropping tasks like I used to, which is the main goal of all of this, right? I do have soft limits in my mind. I try to limit work tasks to 2, personal tasks to 2 or 3, blogging to 1 and Develomatic tasks to 2. Although, even that's not a hard limit because a lot of times I try to batch up a bunch of small unrelated tasks and just knock them out.
Anyway, that's how I've been doing Personal Kanban. Doing something similar, but better? Let me know in the comments!
Full disclosure: As a member of The Lounge, I received a free Personal membership to Zen. Having said that, everything I'm doing for my personal kanban board can be done with the free account.
Categories: Personal
Encrypting and Decrypting Data Using X.509 Certificates
posted on 11/02/09 at 08:24:08 pm by Joel Ross
Over the past few days, I've been working to change our build process and make it a little more flexible for our needs. As part of it, I was asked to look into how we encrypt our data, and see if we could come up with a better way to do it. Right now, we use DPAPI to encrypt information. It works great, but because the encryption is specific to a given machine, it means that encrypted values on one machine can't be decrypted on another machine. If we ever moved to a web farm, we'd be in trouble.
So I started looking at different options for how we could do it. The recurring solution I saw pointed to RSA encryption using X.509 certificates. Since you have the option to export your private keys for these certificates, you can share them across machines and decrypt across a web farm. And all the other side needs is the public key to encrypt the values.
I'm not going to into details about how to get the certificate or export the keys, but there are great resources for creating a test certificate (follow steps 1-3) and for importing and exporting them. These are the two links I used to get my machine ready. Note that in a production environment, you probably want to look at getting a certificate from a trusted certificate authority.
So now you've got your certificate set up, and you want to encrypt something. Now what? Well, don't do what I did my first time implementing it! I went along happily encrypting and decrypting passwords and everything was great. I even rolled the changes out to our team. Then I realized that there's a limit to how much text you can encrypt using this method. Apparently, for a 1024 bit certificate, it's 117 characters. Basically, the formula is (number of bits) / 8 - 11. So a 512 bit key will encrypt up to 53 characters. I don't know enough about encryption to adequately explain why this is, but a few searches turn this up over and over, and my own testing proves this out.
So what to do now? We have strings that can be over 117 characters. After talking it over with a co-worker, I realized that the correct way to go about this is to actually use a symmetric encryption, like AES. But that presents a problem, because both sides need to know the encryption key - a secret that everyone knows! And if we were to use the same key over and over, the encryption could eventually be compromised. So we need to change up the key every time. But how will the other side know the key? That's where the certificate encryption comes in. We encrypt the key and send both the encrypted key and the message to the recipient. The other side grabs the encrypted key, decrypts it using the certificate, and then can decrypt the actual message. From my understanding, this is how SSL works, as well as PGP.
Theory's good, but code is better, right? So how do we do this? First, let's look at how AES encryption works. There's a class in System.Security.Cryptography called RijndaelManaged that implements AES for us. I created a class that wraps the complexity of using it. The constructor takes in an instance of the RijndaelManaged class, and uses that to both encrypt and decrypt data. First, the encryption method.
1: public string Encrypt(string plainText)
2: {
3: MemoryStream msEncrypt = null;
4: CryptoStream csEncrypt = null;
5: StreamWriter swEncrypt = null;
6:
7: try
8: {
9: var encryptor = _aesAlgorithm.CreateEncryptor(_aesAlgorithm.Key, _aesAlgorithm.IV);
10:
11: msEncrypt = new MemoryStream();
12: csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
13: swEncrypt = new StreamWriter(csEncrypt);
14:
15: swEncrypt.Write(plainText);
16: }
17: finally
18: {
19: if (swEncrypt != null)
20: swEncrypt.Close();
21: if (csEncrypt != null)
22: csEncrypt.Close();
23: if (msEncrypt != null)
24: msEncrypt.Close();
25:
26: if (_aesAlgorithm != null)
27: _aesAlgorithm.Clear();
28: }
29:
30: return Convert.ToBase64String(msEncrypt.ToArray());
31: }
The encryption uses the instance filed _aesAlgorithm to perform the encryption, which actually produces a byte array. I then convert that to a string, since that's what I want.
Decrypting data is essentially the same process, but reversed.
1: public string Decrypt(string cipherText)
2: {
3: MemoryStream msDecrypt = null;
4: CryptoStream csDecrypt = null;
5: StreamReader srDecrypt = null;
6:
7: string plaintext;
8:
9: try
10: {
11: ICryptoTransform decryptor = _aesAlgorithm.CreateDecryptor(_aesAlgorithm.Key, _aesAlgorithm.IV);
12:
13: msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText));
14: csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
15: srDecrypt = new StreamReader(csDecrypt);
16:
17: plaintext = srDecrypt.ReadToEnd();
18: }
19: finally
20: {
21: if (srDecrypt != null)
22: srDecrypt.Close();
23: if (csDecrypt != null)
24: csDecrypt.Close();
25: if (msDecrypt != null)
26: msDecrypt.Close();
27:
28: if (_aesAlgorithm != null)
29: _aesAlgorithm.Clear();
30: }
31:
32: return plaintext;
33: }
Now, let's look at the certificate side of things. I did the same thing here too - a class that wraps it and make things easier. But instead of having an algorithm for how the encryption should work (like RijndaelManaged is), this class takes an identifier for the certificate. I used the Thumbprint from it, since that was already in place in other areas for our system, and was a unique value I could grab. So, for this class, I pass in just the thumb print.
Encrypting is pretty simple with a certificate.
1: public string Encrypt(string plainText)
2: {
3: var signatureCertificate = GetCertificate();
4: var rsaProvider = (RSACryptoServiceProvider)signatureCertificate.PublicKey.Key;
5: return Convert.ToBase64String(rsaProvider.Encrypt(plainText, false));
6: }
The complications to the process reside in the GetCertificate() method. Once you have the certificate, encrypting is straight forward. Note that you only need the public key to encrypt - so you can pass around your certificate without the private key and they can encrypt data, but not decrypt it. Only holders of the private key will be able to decrypt it.
Decrypting is just as simple.
1: public string Decrypt(string cipherText)
2: {
3: var signatureCertificate = GetCertificate();
4: var rsaProvider = (RSACryptoServiceProvider)signatureCertificate.PrivateKey;
5: return Encoding.ASCII.GetString(rsaProvider.Decrypt(Convert.FromBase64String(cipherText), false));
6: }
Note here that it's using the private key from the certificate to do the decryption.
The heart of using this method is in actually getting the certificate. To do that, we have a method that retrieves it by it's thumbprint.
1: private X509Certificate2 GetCertificate()
2: {
3: var x509Store = new X509Store(StoreLocation.LocalMachine);
4: x509Store.Open(OpenFlags.ReadOnly);
5:
6: foreach (var storeCertificate in x509Store.Certificates)
7: {
8: if (_thumbprint.ToLower() == storeCertificate.Thumbprint.ToLower())
9: {
10: return storeCertificate;
11: break;
12: }
13: }
14:
15: return null;
16: }
By the way, the actual code is a little more, umm, robust for our purposes, but I eliminated the noise in favor of clarity.
We have the pieces in place for this to work, and now we just need to pull it all together. Again, I made a class that wraps the whole process and makes it easier to use.
First, the encryption part:
1: public string Encrypt(string plainText)
2: {
3: var aesAlgorithm = new RijndaelManaged();
4: var aesDataProtector = new AesDataProtector(aesAlgorithm);
5:
6: var rsaDataProtected = new RsaDataProtector(_thumbprint);
7:
8: var keyCipher = Convert.ToBase64String(rsaDataProtector.Encrypt(Convert.ToBase64String(aesAlgorithm.Key)));
9: var ivCipher = Convert.ToBase64String(rsaDataProtector.Encrypt(Convert.ToBase64String(aesAlgorithm.IV)));
10: var textCipher = aesDataProtector.Encrypt(plainText);
11:
12: return keyCipher + ivCipher + textCipher;
13: }
There's a lot going on here. But here's the gist of it. Get an AES encryption implementation, give it a key and initialization vector (IV. Honestly, I'm not totally clear on how that's used, but it's required and needed later to decrypt the string), encrypt those values using the certificate, encrypt the message with AES, then send them all along for the ride.
Decrypting is similar, except we have to do things in a certain order. First, we have to split the message up into it's three parts. Then we can decrypt the key and IV using the certificate, create our AES implementation using those values, and from there, we can decrypt the message.
1: public string Decrypt(string cipherText)
2: {
3: var rsaDataProtector = new RsaDataProtector(_thumbprint);
4:
5: var keyEnd = 172;
6: var ivEnd = 344;
7:
8: var keyString = cipherText.Substring(0, keyEnd);
9: var ivString = cipherText.Substring(keyEnd, ivEnd - keyEnd);
10: var keyBytes = Convert.FromBase64String(keyString);
11: var ivBytes = Convert.FromBase64String(ivString);
12:
13: var aesAlgorith = new RijndaelManaged
14: {
15: Key = rsaDataProtector.Decrypt(keyBytes),
16: IV = rsaDataProtector.Decrypt(ivBytes)
17: };
18:
19: var aesDataProtector = new AesDataProtector(aesAlgorith);
20: return aesDataProtector.Decrypt(cipherText.Substring(ivEnd, cipherText.Length - ivEnd));
21: }
Most of this is basic string manipulation. Again, for simplicity, the keyEnd and ivEnd values are hardcoded (and work with a 1024 bit certificate), but in my app, they are determined by the location of terminator values. I'll leave that part as an exercise for the reader. But note that encrypted values are typically terminated by an equals sign.
And that's pretty much it. The nice thing about this is that the only thing both sides need to know are details about the certificate. And if someone just wants to send you an encrypted value, you give them your public key, and that's it. No exchange of secrets at all!
Categories: Development, C#
TrackAbout Is Hiring!
posted on 10/18/09 at 10:39:08 pm by Joel Ross
It's been almost a year since I started at TrackAbout, and so far, it's been one of the best decisions I've made. I absolutely love working from home, and the team I work with is extremely talented. We're a small company, but looking to grow the team very soon. We're going to add a couple of developers, and we're specifically looking for an experienced developer with compact framework experience. We're doing a lot of work in that area, and getting someone with knowledge there would be hugely beneficial. We're also seeking a QA lead, but unlike the development positions (which are both work from home), this would be in Pittsburgh.
There isn't a job posting for these anywhere, and I think part of that is because we want to see what kind of people we can find on our own through our blogs or twitter. Last year, there was a job posting, but both of us that joined TrackAbout found out about the position through blog posts (well, technically, I found it on twitter, but it was a link to Joey's blog). I think we'll find better and more qualified candidates this way, so I'm excited to see who responds.
If you're interested, please let me know. I know a lot don't necessarily want it to be public knowledge that they may be interested in another job, so feel free to email me rather than comment (jross at rosscode dot com), or check out my contact page for more options. I'd be glad to have a chat via IM, Skype or phone.
For a bit more information, check out this guest post by my boss about how we communicate on a daily basis and some of the tools we use. Also, here's part of the blurb from the last job posting TrackAbout posted.
Company:
TrackAbout, Inc.
www.trackabout.comTrackAbout is a small, profitable and growing software company that provides Software as a Service (SaaS) asset tracking services through the combination of a hosted web platform and various mobile devices that run our custom software. We have a solid, international customer base, are experiencing high demand for our services and are looking at exciting times ahead. We are looking for an exceptional and experienced developer who is interested in playing a pivotal role in the growth of a small company. If you're truly passionate about technology, we want to talk to you.
Location:
TrackAbout's main office is just outside of Pittsburgh, PA. However, our development staff is completely virtual (no office) and each developer works from home.All members of our development team are dedicated to keeping up with the latest techniques, technologies and tools related to software development. We take time out to share our knowledge with one another and improve both our skills and our distributed development environment. We often experiment with and integrate new tools into our environment. We use ReSharper, CruiseControl.NET, TDD with NUnit, FXCop, NCover, Bugzilla, and Drupal to supplement our development efforts.
Categories: ASP.NET
Essential Versus Accidental Tasks
posted on 10/13/09 at 08:00:00 pm by Joel Ross
I finished reading Mythical Man Month a while ago. [Actually, it was a LONG while ago, but this post has been in my draft list for well over a year!] Overall, I thought it was a good book, but not as good as I expected. I think part of it was the amount of praise the book receives, and part was how good the first few chapters were - they left an expectation for the rest of the book, and it just didn't seem to live up.
Anyway, one of the chapters (No Silver Bullets, I think) talks about whether software development techniques can get an order of magnitude increase in efficiency, and lays out development tasks in two categories:
- Essential Tasks: The tasks that are directly related to building the software. Basically, writing code.
- Accidental Tasks: The tasks that you have to do to build software, but aren't technically part of the software.
The essay goes on to talk about how accidental tasks would have to be 90% of development time in order to get an order of magnitude reduction development time if you could remove them all, and how that's unreasonable. As a result, you have to attack the essence of software development if you want to achieve those types of results.
It's a logical argument. And while eliminating (or greatly reducing) the accidental tasks won't yield an order of magnitude speed up in development, it doesn't take a huge effort to reduce the accidental tasks either. Before you can determine if it's worth reducing the accidental tasks though, you need to know how much time they actually take. If they only take 5% of your time, any effort towards reduction will seem wasteful with respect to the return. But if the accidental tasks start to approach 1/4 to 1/2 of your time, then reducing that will yield much larger returns.
Before we can answer how much time accidental tasks take, we should probably define what the accidental tasks are. Some of these may seem controversial, but remember, accidental tasks are anything that's not essential to the production software.
- The build process: On a lot of projects, this can be a major time sink. I've seen projects that do a weekly integration cycle and it can take one person a few hours every week just to get the software built and deployed. Even automated builds can be a time sink, both with the time to set up and maintain the build, but also the ongoing build tax - think "Check-in dance."
- Environment setup: Creating a development environment takes time. This includes setting up source control, getting the right people access, installing the necessary software and tools, setting up a QA/Test environment, etc. All of the "infrastructure"-type tasks.
- Testing: This'll probably be the most controversial task on the list. But the reality is that manual testing takes time. Writing automated tests takes time, and while they have great value in creating correct code (and solid design), the tests themselves aren't production code. Plainly, tests aren't deployed.
- Project Administration: Status meetings, time tracking, billing, code reviews, etc. Important pieces, to be sure. But not essential to the software.
- Bug Fixes: This one's a bit different, because this code actually does make it into production. But I'm including it here because bug fixes aren't essential to the advancement of new features - they're flaws in features already completed. Had it been done correctly to start with, this time wouldn't be necessary.
I'm sure there are other components I'm missing, but those would be the major "accidental" tasks I see. The first two are basically setup costs. They are essentially a "one time fee". And they're roughly the same for any new projects, big or small. That causes a bit of a conundrum. On large or long running projects, the savings (percentage-wise) is small, so the incentive to figure out a way to reduce it is small. On smaller projects, the savings (percentage-wise) is bigger, and so is the incentive to automate it away. What isn't there is the extra time needed to figure out how to automate those tasks away. If you rarely start new projects, then reducing setup costs isn't a big deal.
So, that really leaves the last three as ways to get significant gains by reducing accidental tasks. They're all repeating tasks, and could easily account for 25% of a project team's time, and that doesn't include the time lost to context switching. Moving to a leaner project management approach will help reduce project administration, but for most organizations, this is a fixed item without a lot of flexibility. If you're consulting, you need to track hours and project status so you can get paid. You can optimize it, but most likely, it's been optimized if the company has been around for any significant time.
So that leaves testing and bug fixes. Ironically, increasing one will reduce the other. The more time you spend testing, the less bugs you'll have. But manual testing takes a lot of time, so the most efficient use of a team's time is looking for ways to automate the testing process. Things like unit tests, integration tests, functional tests, UI tests - anything that can be automatically run in a repeatable fashion - this is where you can gain some real benefits. The payoff: you'll spend a lot less time fixing bugs, which means your team is moving forward, not looking back. Also of note, investing time into automated testing will make your software easier and safer to modify over time, and will actually reduce the time it takes to do the essential tasks.
I took the long way to get here, but the bottom line is this: Increasing one aspect of an accidental task will decrease other aspects of accidental tasks, as well as streamlining essential tasks. Sounds good to me!
Categories: Development, Software
Dynamically Loading Config Files
posted on 09/08/09 at 12:52:01 am by Joel Ross
In my last post, I talked about dynamically loading and unloading DLLs. It works well, but I quickly ran into an issue: configuration data. The main application, which is what houses the DLL that's loaded dynamically, has a lot of configuration data, and I need that to do the processing I need to do.
Since one of the main requirements for the secondary application was that it had to have near 100% uptime, I couldn't include all of the main app's configuration in the secondary app's config - because it might get updated with new builds, which would require the secondary app to restart. So, I started looking at how you can load a configuration file dynamically. As usual, it's pretty straightforward:
1: var map = new ExeConfigurationFileMap {ExeConfigFilename = @"C:\Bins\app.config"};
2: ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
Now, the DLL can load its own configuration information on the fly. For my application, I added a method to my BaseType abstract class:
1: public abstract void InitializeConfig(string configPath);
By implementing this method, I can now initialize the config from the secondary application after it loads the DLL, and all the secondary app has to know about is the location of the config file the main application uses.
Categories: Development, C#