Here’s a quick little wrapper class for an undocumented method in user32 library called MessageBoxTimeout.
There are all sorts of little file encryption utilities out there but you never know exactly whats going on inside of them and if they are doing things the right way or not so I thought I’d build a tiny little lightweight file encryption utility and then explain whats going on inside.
The Encryption
First of all I’m using the FIPS compatible CNG library and am using AES256 as my base encryption algorithm.
The Key
To generate the secret key from a password I use a salted KDF function with 1,000 iterations to create a secret key for encryption. The key is kept in memory for only as long as it needs to be in memory but while it is in memory it is protected using the DPAPI (Data Protection API) and is only unprotected for the split second that the data is being encrypted and is then protected again.
Tamper Proof
The data is also signed by an HMAC function to generate a signature to verify that the encryption has not been tampered with as there are tamper attacks. This allows you to save the file anywhere and as long as you have the original password the contents of your file should be both safe and tamper proof.
Zeroize the Plaintext File
Last but not least, there is a slight problem. The original file remains on your computer. This may not be a problem but if you have a scenario in which you want to encrypt a file in such a way that the previous file no longer exists on your hard drive your out of luck. Even if you delete the file it still exists and is retrievable from your hard drive. Enter, SDelete. SDelete is a utility that not only deletes a file but it writes over the file on the hard drive with random data N number of times. To use this, in FileCrypto you simply check the ‘Delete Previous File’ checkbox. This will encrypt your file and delete the previous file.
Tutorial
While the program is exceedingly easy to use… why not have a tutorial?
- Make sure you have .net4 installed.
- Download the program
- Extract and run FileCrypto.exe
- Click ‘Select File’ and click on the file you wish to encrypt
- Check the ‘Delete Previous File’ checkbox if you wish to securely delete the un-encrypted file
- Click the ‘Encrypt’ button
- Type in a password you wish to encrypt with. DO NOT FORGET THIS PASSWORD!!!
- Click ‘OK’
To decrypt, just follow the same steps just clicking Decrypt instead. Easy enough?
Legal Crap
This software is provided AS IS. I’m not liable for anything to do with this program. If you encrypt a file with a password and then forget the password or can’t decrypt the file, sorry, can’t help you. This program was written for myself and what I needed it to do and I’m sharing it freely. Please feel free to use it for whatever you want to use it for as long as what you are using it for is legal. If you do something illegal with it, screw you, I’m not liable. Individuals or corporations can use it, I don’t really care have fun.
.
BouncyCastle is a really powerful encryption library that most Java developers will know about. It has been a fundamental library for many years now. They also have an inter-operable library for C# that can be compiled in the full .net framework and Silverlight. Most .net developers use the CNG library wrapper class library which has advantages such as some FIPS certifications. However, that is only implemented as of Vista and above and is not implemented in platforms such as Silverlight or any of the Mono or MonoTouch frameworks so there are still compelling reasons to use BouncyCastle in C#. In an ideal world you should be able to encrypt/decrypt across all libraries and, as it turns out, you can. Ok, I’ll shut up and get to the code. The following is an example of using BouncyCastle in Java, C# and an equivalent example in .net CNG:
// C# BouncyCastle public static byte[] Encrypt(byte[] input, byte[] baseKey, byte[] HMACKey) { byte[] cryptKey = new byte[32]; // Generate initialization vector byte[] iv = GenerateCryptoRandomByteArray(16); Array.Copy(baseKey, 0, cryptKey, 0, 32); ParametersWithIV key = new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", cryptKey), iv); IBufferedCipher outCipher = CipherUtilities.GetCipher(NistObjectIdentifiers.IdAes256Cbc.Id); outCipher.Init(true, key); byte[] bytes = outCipher.DoFinal(input); byte[] hmac = HMACSignBytes(HMACKey, bytes); byte[] result = new byte[bytes.Length + iv.Length + hmac.Length]; Buffer.BlockCopy(bytes, 0, result, 0, bytes.Length); Buffer.BlockCopy(iv, 0, result, bytes.Length, iv.Length); Buffer.BlockCopy(hmac, 0, result, bytes.Length+iv.Length, hmac.Length); return result; } public static byte[] HMACSignBytes(byte[] Key, byte[] Data) { HMac hmac = new HMac(new Sha512Digest()); byte[] resBuf = new byte[hmac.GetMacSize()]; hmac.Init(new KeyParameter(Key)); hmac.BlockUpdate(Data, 0, Data.Length); hmac.DoFinal(resBuf, 0); return resBuf; } public static byte[] GenerateCryptoRandomByteArray(int length) { byte[] buffer = new byte[length]; SecureRandom sr = new SecureRandom(); sr.NextBytes(buffer, 0, length); return buffer; }
// Java BouncyCastle public static byte[] Encrypt(byte[] input, byte[] baseKey, byte[] HMACKey) throws EncryptionException { try { // Generate initialization vector byte[] iv = EncryptionEngine.GenerateCryptoRandomByteArray(16); Key key = new SecretKeySpec(baseKey, "AES"); Cipher outCipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); outCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); byte[] bytes = outCipher.doFinal(input); byte[] hmac = HMACSignBytes(HMACKey, bytes); byte[] result = new byte[bytes.length + iv.length + hmac.length]; System.arraycopy(bytes, 0, result, 0, bytes.length); System.arraycopy(iv, 0, result, bytes.length, iv.length); System.arraycopy(hmac, 0, result, bytes.length+iv.length, hmac.length); String hexhmac = new String(Hex.encode(hmac)); String hexiv = new String(Hex.encode(iv)); String hexcipher = new String(Hex.encode(bytes)); return result; } catch(Exception ex) { throw new EncryptionException(ex); } } public static byte[] GenerateCryptoRandomByteArray(int length) { byte[] buffer = new byte[length]; SecureRandom sr = new SecureRandom(); sr.nextBytes(buffer); return buffer; } public static byte[] HMACSignBytes(byte[] Key, byte[] Data) { HMac hmac = new HMac(new SHA512Digest()); byte[] resBuf = new byte[hmac.getMacSize()]; hmac.init(new KeyParameter(Key)); hmac.update(Data, 0, Data.length); hmac.doFinal(resBuf, 0); return resBuf; }
// C# CNG public static byte[] Encrypt(byte[] srcBytes, byte[] baseKey, byte[] HMACKey) { // Encryption will be performed using memory stream. MemoryStream memoryStream = new MemoryStream(); // Let's make cryptographic operations thread-safe. lock (lockObj) { byte[] IV = EncryptionEngine.GenerateIV(); ICryptoTransform encryptor = BuildEncryptor(baseKey, IV); // To perform encryption, we must use the Write mode. CryptoStream cryptoStream = new CryptoStream( memoryStream, encryptor, CryptoStreamMode.Write); // Start encrypting data. cryptoStream.Write(srcBytes, 0, srcBytes.Length); // Finish the encryption operation. cryptoStream.FlushFinalBlock(); // Move encrypted data from memory into a byte array. Byte[] cipherTextbyte = memoryStream.ToArray(); List<byte> cipher_IV_HMAC = new List<byte>(); cipher_IV_HMAC.AddRange(cipherTextbyte); cipher_IV_HMAC.AddRange(IV); cipher_IV_HMAC.AddRange(HMACSignBytes(HMACKey, cipherTextbyte)); // Close memory streams. cryptoStream.Close(); memoryStream.Close(); encryptor.Dispose(); return cipher_IV_HMAC.ToArray(); } } public static byte[] GenerateIV() { using (AesCryptoServiceProvider am = new AesCryptoServiceProvider()) { am.GenerateIV(); return am.IV; } } public static byte[] HMACSignBytes(byte[] Key, byte[] Data) { using (FIPSHmacSha512 hmac = new FIPSHmacSha512(Key)) { byte[] HashValue = hmac.ComputeHash(Data); hmac.Dispose(); return HashValue; } } internal class FIPSHmacSha512 : System.Security.Cryptography.HMAC { public FIPSHmacSha512(byte[] key) { if (key == null) throw new ArgumentNullException("key"); HashName = "System.Security.Cryptography.SHA512CryptoServiceProvider"; HashSizeValue = 512; BlockSizeValue = 128; Key = key; } }
“Ok,, what the heck am I looking at?!?!?”. Well here’s what happens, each one of these functions is ultimately doing the same 3 things:
- Generating a Nonce (Number Used Only Once) for the initialization vector that AES 256 requires
- Encrypt the data
- Sign the cipher text with an HMAC function
First, the initialization vector is required as we are using AES256 CBC block mode I won’t go into more detail on the specifics of why we use CBC but suffice it to say, CBC is much stronger than some of the other block modes such as ECB especially if you need to encrypt the same data more than one time with the same secret key. This block mode requires an initialization vector that uses a crypto pseudo random function. There are many people who have used linear congruential random generators by mistake instead of a strong random generator such as earlier versions of Kerberos. Don’t make that mistake! If an attacker can predict the next number in a random number used, it weakens if not completely compromises the cipher strength.
Next, we encrypt the data. Woo hoo! A couple things to note, we are using PKCS7Padding. All three functions must use this padding to be inter-operable. This helps to reduce the predictability of the plaintext.
Next up, we sign the cipher with an HMAC function. Why do we do this? Well as it turns out there even though a cipher may not be decrypted, it can be modified. There are several possible attacks against ciphers that can modify the original plain text so we use an HMAC function to sign the cipher. This means that during our decryption we must verify the HMAC signature with the original HMAC key to verify that the original cipher has not been tampered with in any way. Finally we just append all the data together in one big cipher package that we can pull apart and decrypt with later.
So to decrypt… well.. how about we just look at code…
// C# BouncyCastle public static byte[] Decrypt(byte[] input, byte[] baseKey, byte[] HMACKey) { byte[] hmac = new byte[64]; byte[] iv = new byte[16]; byte[] cipher = new byte[input.Length - 16 - 64]; byte[] cryptKey = new byte[32]; Array.Copy(input, input.Length - 64, hmac, 0, 64); Array.Copy(input, input.Length - 64 - 16, iv, 0, 16); Array.Copy(input, 0, cipher, 0, input.Length - 16 - 64); Array.Copy(baseKey, 0, cryptKey, 0, 32); string hexkey = Hex.ToHexString(baseKey); string hexhmackey = Hex.ToHexString(HMACKey); string hexhmac = Hex.ToHexString(hmac); string hexiv = Hex.ToHexString(iv); string hexcipher = Hex.ToHexString(cipher); if (!HMACVerifyBytes(HMACKey, hmac, cipher)) { throw new Exception("HMAC is invalid"); } ParametersWithIV key = new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", cryptKey), iv); IBufferedCipher inCipher = CipherUtilities.GetCipher(NistObjectIdentifiers.IdAes256Cbc.Id); inCipher.Init(false, key); return inCipher.DoFinal(cipher).ToArray(); } public static bool HMACVerifyBytes(byte[] Key, byte[] HMACSignature, byte[] Data) { byte[] signature = HMACSignBytes(Key, Data); if (signature.SequenceEqual(HMACSignature)) { return true; } else { return false; } }
public static byte[] Decrypt(byte[] input, byte[] baseKey, byte[] HMACKey) throws EncryptionException { try { byte[] hmac = new byte[64]; byte[] iv = new byte[16]; byte[] cipher = new byte[input.length - 16 - 64]; System.arraycopy(input, input.length - 64, hmac, 0, 64); System.arraycopy(input, input.length - 64 - 16, iv, 0, 16); System.arraycopy(input, 0, cipher, 0, input.length - 16 - 64); if (!HMACVerifyBytes(HMACKey, hmac, cipher)) { throw new Exception("HMAC is invalid"); } Key key = new SecretKeySpec(baseKey, "AES"); Cipher inCipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); inCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); byte[] results = inCipher.doFinal(cipher); return results; } catch(Exception ex) { throw new EncryptionException(ex); } } public static Boolean HMACVerifyBytes(byte[] Key, byte[] HMACSignature, byte[] Data) { byte[] signature = HMACSignBytes(Key, Data); if (Arrays.areEqual(signature, HMACSignature)) { return true; } else { return false; } }
// C# CNG public static byte[] Decrypt(byte[] srcBytes, byte[] baseKey, byte[] HMACKey) { List<byte> SourceBytes = new List<byte>(srcBytes); //Extract the cipher, initialization vector and the hmac byte[] cipher = SourceBytes.GetRange(0, srcBytes.Length - 80).ToArray(); byte[] IV = SourceBytes.GetRange(srcBytes.Length - 80, 16).ToArray(); byte[] HMAC = SourceBytes.GetRange(SourceBytes.Count - 64, 64).ToArray(); // Validate HMAC if (!HMACVerifyBytes(HMACKey, HMAC, cipher)) { throw new Exception("HMAC is invalid"); } // Encryption will be performed using memory stream. MemoryStream memoryStream = new MemoryStream(cipher); // Let's make cryptographic operations thread-safe. lock (lockObj) { ICryptoTransform decryptor = BuildDecryptor(baseKey, IV); // To perform encryption, we must use the Write mode. CryptoStream cryptoStream = new CryptoStream( memoryStream, decryptor, CryptoStreamMode.Read); byte[] source = new byte[memoryStream.Length]; // Start decrypting data. int byteCount = cryptoStream.Read(source, 0, source.Length); byte[] ReturnSource = new byte[byteCount]; Buffer.BlockCopy(source, 0, ReturnSource, 0, byteCount); // Close memory streams. cryptoStream.Close(); memoryStream.Close(); decryptor.Dispose(); return ReturnSource; } } public static bool HMACVerifyBytes(byte[] Key, byte[] HMACSignature, byte[] Data) { using (FIPSHmacSha512 hmac = new FIPSHmacSha512(Key)) { byte[] HashValue = hmac.ComputeHash(Data); hmac.Dispose(); return HMACSignature.SequenceEqual(HashValue); } }
The process in reverse. We simple take apart that which we have created and decrypt it. It starts by verifying that the signature is the same so we know that the cipher has not been tampered with. Then we extract the IV and use that as well as the secret key to decrypt our data and return our original plaintext, or in this case, a byte array.
I am, over the next several months, going to attempt to brooch the subject of security. This is a subject full of controversy, misinformation (or lack of information), and a general lack of understanding of what security is, who are we defending against, how ‘they’ (whomever they may be) will try to attack us.
The Problem
Security is defending against infinity and infinity keeps changing. The interesting thing about security is that there is no way to always know who the attackers will be, how they will attack or for that matter, if they were successful in their attacks or not. Another problem is, what kinds of security tools exist to help protect a system against attacks? Which of course leads to another problem, what kind of attacks exist against these tools and how do you implement these tools properly? These are problems that I’ve been facing lately with a large project I’ve been tasked to work on and I’ve been on a journey to discover the answers to these problems and thought I’d share.
Wax On, Wax Off
So how does one start out as a grasshopper and become a jedi master? Well a great way to start is to learn from the masters, but first, we have to know who those masters are. Here are just a couple of masters that you should know:
- Bruce Schneier: Security expert and author. He is a great, comprehensive teacher and has written several books on cryptography and even more importantly, how to implement cartographic systems. He also has a great blog on security.
- Alfred Menezes, Paul van Oorschot and Scott Vanstone: Co-authors of several cryptography books most notably The Handbook of Applied Cryptography
- Whitfield Diffie: A security expert and the co-inventor of the Diffie-Hellman key exchange algorithm.
- Adi Shamir: Inventor of RSA and numerous other cryptographic algorithms.
“Your done?!?!!?” cryptography masters scream, and I respond, “so sorry, I just don’t have time/patience to reference every single security master”. These are just a couple guys to know about but you should learn about more of the masters.
What Exactly Is Security?
Security, in short, is either two things. #1 Complete void of access: Scenario, you have a document on a computer in a metal room with big locks on the doors and there is no network connections of any kind to this computer. #2 Cryptography: Assuming that you require access to data, cryptography is the over-arching solution.
Security Principals
Kerckhoffs’s principle
Only secrecy of the key provides security. You are not required to show the world your code, however, your dependence on security must be based on the cryptographic keys being secret. Any dependency beyond this is false security. We have seen time and time again that a determined attacker can, and will, thwart any security system that is dependent on anything other than the secrecy of the cryptographic key.
Security By Obfuscation
There are many companies/organizations who think of obfuscation as a defense when all obfuscation can ever be is a deterrent. Any determined attacker can, eventually, get past obfuscation especially when your talking about a published solution. The mindset of a security expert is to assume the enemy knows the internals of the system and design the system so that the attacker still cannot breach it. The ‘enemy’ could be anyone. It could be someone in an organization. It could be a designer or developer of the security system! The goal should always be that even if you know the entire system from start to finish, you still could not breach the security within a reasonable amount of time. There are some good reasons for obfuscation, code obfuscation for instance. That can help to deter individuals from stealing your product and make it slightly harder for an attacker to understand how your system works, but you must never think of obfuscation as a defense.
Futility
“It is futile to lock the barn door after the horse has been stolen”. This is a great concept that has many implications. One of these implications is that security must extend from the source, all the way to the destination. If there is a section of the data’s journey in which the attacker is able to get the data, all has been for naught.
The Weakest Link
“Security is only as strong as the weakest link”. It doesn’t matter how thick and strong 299 links in a powerful chain are, if the 300th chain in the very center of the chain is made of thin, weak tin, the entire chain is as strong as weak tin. Any attacker who is worth his salt is not going to start an attack at the thickest point in the chain, he is going to go straight for the weakest link in the chain to break through.
Over the next few months I’ll be talking more about my journey through security and will hopefully help myself and others have a better understanding of security

I’ve not blogged for a while for one reason. I’m tiring of the environment of negativity, flaming and bashing when it comes to the web world. It’s literally like we’ve become vampires vs lycans fighting each other. Choose your side! RIA or web standards! However, there are a few real programmers out there who aren’t driven by fear or what they’ve read on the internet. Programmers who take a pragmatic look at technologies and find out what they really do at a lower level and how they do it and to find out what the true pros/cons are and then make an informed decision per project. This is a wonderful article that mirrors this approach http://blogs.forbes.com/fredcavazza/2011/07/17/why-opposing-html5-and-flash-is-a-non-sense/.
Highlights: Dire Predictions

"…writing about the agony of Flash is an easy way to draw readers". This is the bottom line. Technology bloggers these days are passing themselves off as "professionals you should listen to" when in reality they are simply little people who gained a little bit of knowledge without really getting their hands dirty. They use familiar tactics such as the ones used by today’s media writing about the END OF THE WORLD only to get more people watching/reading and produce higher ratings. This is what you are buying into when you read articles that hype about HTML5 killing Flash or Silverlight. I remember not very long ago the opposite was true. People were proclaiming the death of HTML and Flash would "take over". These days, anyone can make predictions, scare a bunch of people and get hits on their websites. Do they get ‘dinged’ for when those predictions do not come true? Nope. People just forget. I remember 10 years ago Linux gurus telling me that Linux was going to take over windows in 10 years.
When does the insanity end?
It ends when you, a developer, stops listening to fear and remember what drove us as developers in the first place. Curiosity! Exploration! That’s why we do what we do and those who are explorers and pioneers are not blinded by fear-mongering idiots who don’t know their thumb from their… toe. Explore other programming languages and technologies that you aren’t familiar with! Keep your mind open and be honest with yourself about the pros and cons of all technologies.
I’ve been preaching the gospel of security for years. The response? Typically something like this *Glazed over eyes* ‘hmm,, wow,, hmm yeah,, um,, that’s interesting we should look into that’ or ‘Wow, your paranoid aren’t you’ or ‘Oh no one could figure out how to hack into our web application’ (that one is a particular favorite). The fact is this. Crackers (notice I did not say Hackers as a Hacker is ethical and a ‘Cracker’ just wants to ‘crack’ a system and cause trouble), are out there. Everywhere. And they are becoming more sophisticated. For a while it seemed that most Crackers were just looking for weaknesses. Any website, application or network that had gaping security holes were exploited. Just this past week 2 of my friends GMail accounts were hijacked and I received spam email from them. They took their laptops to an open wifi and checked their email and they were had. Even more interesting there are much more sophisticated techniques such as a group of Russian Hackers who developed a way to hack into an encrypted wifi network by obtaining the wifi key and brute force attacking the key using your Nvidia graphics card http://www.tomshardware.com/news/nvidia-gpu-wifi-hack,6483.html. This is also a technique that is taking over brute force password cracking by storm as you can tens of millions of tries per second. All of this sounds technical and hard to do, but the exact opposite is true. Its easy. Not for some technical guru but for anyone who is remotely interested in hacking. These days we have very sophisticated tools that have easy to use GUIs and lots of youtube tutorials on how to use them such as Cain & Abel by oxid.it which is a very powerful network hacking tool (among other things). Hey, these days you don’t even need to do anything more than press a button to hack someones website with tools such as Firesheep which uses session hijacking to allow an unauthorized user to appear as an authorized user. To top it all off the amount of hacking is increasing by an alarming rate. Recently we have Sony, CitiGroup and the CIA (just to name a few). Not all system cracks are more sophisticated though, some are just more of the same thing. CitiGroup for example. The crackers were able to get a list of account numbers and retrieve sensitive information simply by plugging in the account numbers in a string in the address bar of a browser. Obviously a company who decided not to take security seriously.
Easy Conclusion
Security isn’t an option. It never has been and the feeble excuses developers make to try and get out of doing the right thing are being stripped away. There is nothing left except to learn about security and implement it. And how do we implement security? By becoming hackers ourselves. We have to read what hackers are saying and get our hands dirty trying to hack systems. When we do, our eyes are opened to just how easy it is for a determined person to get into a system and then we are able to put up walls to stop it.
Am I paranoid? Well the word paranoid means someone who has undue fear of something that really doesn’t exist. Well, unless I missed it, I think that the evidence clearly shows that crackers most definitely do exist and they are very active and they can/will attack you at some point. The opposite of course is ‘Naive’ which means someone who has a very simple nature and a great lack of experience and judgement. Anyone who thinks that security isn’t paramount in application development or network/server administration and shouldn’t be given extra attention should have their head examined. We as developers cannot afford to have our heads stuck in the sand anymore. The crackers are simply not going away. They are growing in numbers and sophistication and so must we.
And here’s a list of the new features http://i1.silverlight.net/content/downloads/silverlight_5_beta_features.pdf?cdn_id=1. A couple of the main features I took note of was the ability to do COM and pInvoking in or out of browser. Currently Silverlight4 allows out of browser trusted apps to do COM but this moves towards the ability to interact with software such as Office or physical devices such as medical etc within the browser itself and not have to install it as an out of browser application. Another great feature to take note of is the ability to put breakpoints in the XAML code where you are binding to a datasource. This is very handy for troubleshooting and debugging. There are tons more features to check out so have fun!
I just read this blog post written by Dean Wilson and it really got me thinking about the difference between those who play with technology and like to think that they actually know something about it and those who actually work with it in depth and understand the purpose of the technology. The problem with those who play and have opinions is that they only understand the purpose of the technology in their own sphere of life experiences. So, in answer to Dean Wilsons’ article I would like to explain (once again) why Silverlight exists and why it isn’t here to threaten HTML5.
The Purpose
The purpose of Silverlight is NOT ONLY VIDEO!!!! It is also to give developers capabilities that they do not have given the Javascript/HTML5/CSS environment, and yes, I mean desktop browser applications not just Microsoft Phone. Currently there are several things that Silverlight has that HTML5 doesn’t have and no one is talking about ever adding these capabilities which, I might add, is not necessarily a bad thing. So what are these capabilities that I’m speaking of? Here’s a list. And please please please keep in mind that this IS NOT AN HTML5 BASHING SESSION!!!! I am very simply, pragmatically as possible listing what Silverlight can do that HTML5 cannot do and many times shouldn’t do. I’m both an HTML5 and Silverlight developer.
The Capabilities
- Powerful client/server encryption.
* Javascript simply doesn’t numbers big enough to handle the calculations needed to produce very powerful algorithms such as AES where Silverlight can handle these types of algorithms in applications that require the highest amount of security.
- Multithreading
* Javascript is currently single threaded. Google gears introduced the ‘Worker Pool’ and HTML5 is bringing ‘Web Workers’ but it is still not true threading (not to diminish this new exciting feature for HTML5 however). Silverlight is truly multithreaded and there are many advantages to this.
- File System Access
* Javascript and HTML5 do not have access to the file system where Silverlight does. There is no one talking about giving this ability to Javascript or HTML5 for security reasons, however in cases where this would be necessary Silverlight is a good alternative.
- Printing
* The only capabilities that Javascript/HTML5 has when it comes to printing is to tell the browser to print the current page. Silverlight offers more capabilities to make adjustments when printing and to select what objects to print and what objects to exclude.
- Web Cam
* Silverlight 4 introduced some great new features for accessing a web camera and streaming video to your Silverlight application. There are a lot of amazing possibilities especially since you can control and edit and filter the video.
- Client Side File generation
* Many web applications have ways of exporting data sets displayed in your app to a file format such as excel or PDF. All of this must occur on the server side and then download the file to the client computer. All of which takes a lot of resources if there are many users doing this at once. Silverlight offers the ability to generate PDFs, Excel documents and much more on the clients computer thereby reducing the amount of processing required on the server and reducing the amount of data going over the wire and effectively distributing the work load amongst many computers.
- Binary Compression
* There are many ways in which you can compress the data going to and from your browser. GZIP being one of the more common. Silverlight offers binary encoding for its data which is much more compressed than GZIP and it raises performance.
- Network Performance
* Modern browsers allow you to connect to a maximum of 2 simultaneous connections at a time (unless you go to about:config or something similar and manually change underlying settings) whereas Silverlight allows for up to 6 simultaneous connections. As of Silverlight 5, Silverlight will be utilizing Low Latency networking as well improving performance even more.
- COM Interop
* Some think that this is a thing of the past, however there are many instances in which the need arises to be able to interact with COM. For instance you need to access a COM enabled application such as Microsoft Office. You can send emails through Outlook, or get data from an Excel Spreadsheet. Silverlight has the capability to extend its reach into the COM environment in Out Of Browser, Trusted applications for scenarios. With Silverlight 5 we are being given the capability to p-invoke the Windows API which gives even more capabilities. For instance being able to connect with a physical device of some kind such as medical equipment.
- Out Of Browser Offline
* While Google Gears gives some of this capability, Silverlight offers the ability to have online/offline mode and actually be installed as an application to be run outside of the browser.
- True 3D environment
* Silverlight 5 is also offering the capability to render a true, hardware accelerated 3D environment. There are many very good looking simulations of this in Javascript such as webGL however it lacks many needed capabilities to truly create, say for instance, a first person shooter. This really opens the doors for game developers who want to build high quality 3d games that run in your browser.
- Video Streaming
* While it is true that HTML5 has a video player, no one seems to mention that it does not have anywhere near the capabilities that Silverlight has with smooth streaming, 1080p quality, the ability to completely customize the player, slow motion (with audio pitch correction in Silverlight5) etc. While Silverlight is certainly not only about video, it shines in this area.
- Cross Platform
* One of the biggest issues as an HTML5 developer is running into browser compatibility issues. Is this getting better? Yes and no. Yes in the sense that Microsoft has ’seen the light’ and realized (admittedly) that IE6 was a very very very bad idea and standards in HTML are very important. Hence, IE9 is going to make our lives easier. However we have more browsers to deal with today than we did a few years ago and there are still many compatibility issues to deal with that can suck a lot of time out of a developers life. Silverlight (since it is a browser plugin) works across Windows/Mac (and arguably Linux with the Moonlight project) and works in all major browsers without the types of layout and scripting compatibility issues we’ve seen with HTML/Javascript. Instead of having 5 browsers open to test, you can just run it in one browser and your assured it will work in all the others the same way.
- Other Design
* There are many other design aspects of Silverlight that are very welcomed in the world of design. Rounded corners for instance. HTML5/CSS3 finally introduces this as well http://www.css3.info/preview/rounded-border/ with some browser. Not all support this yet. It also has the ability to do other things such as drop shadows, glow effects, gradients and much much more all in your layout code without ever having to touch photoshop. This is advantageous because you no longer have to store the PSDs externally to your project, its all in code, not to mention you don’t have to download all those extra images. Speaking of images there are a plethora of image effects that you can apply client side to images that you load in your app.
- Development Environment
* Very large enterprise applications can get a lot of spaghetti code really fast if your not careful. C# is a very robust language that has many features that Javascript doesn’t have that are very useful to Enterprise level applications such as Classes, Interfaces, Abstract Classes, Typed object lists and many more features that would take many more articles to cover so I won’t even try to go over it all here. Other features include code compilation, more comprehensive unit testing, performance analysis tools, very powerful UI scripted tests, more powerful exception handling even at a global level (which is very important for error logging). Debugging abilities include the ability to put breakpoints in all areas of your code even in the design layout XAML (coming up in Silverlight 5).
- Development Tools
* One area of development particularly found in Design/Development firms is the disconnect between designers and developers. Each developer reading this who has ever worked with a Designer has some story of some design that seemed artistic to the designer but ended up being nightmarish to implement. One of the tools that Silverlight offers is Blend. Blend is a design tool that has the look and feel of programs such as Photoshop and even has simple tools for creating design elements such as shapes, gradients etc. This coupled with an image editing application gives designers much more power and developers less headache. The beauty of this is that whatever the Designer creates in Blend is immediately translated into XAML code that is automatically decoupled from the developers C# code effectively shrinking the gap between designers and developers. This isn’t a silver bullet mind you but it is moving in the right direction.
So whats your point? Should we only use Silverlight?
That is absolutely not my point. There are many scenarios in which Silverlight is a terrible idea. Say for instance you want to have a very content driven website that is very visible to search engines. Silverlight is most definitely NOT a good option for something like that. Also, while the number of computers that currently have Silverlight already installed is growing at an astounding rate given the short time Silverlight has been around, it is STILL a plugin and you STILL have to install it before your application will work. Most of the time this truly isn’t a problem given that people are already installing a plethora of plugins ranging from quicktime, flash, windows media, adobe reader, java and an infinite number of firefox/chrome/IE plugins. However there are still those who don’t like it so you have to know your audience. So there are many scenarios in which HTML5 IS the better option.
Conclusion
This is not an exhaustive list of Silverlight features. There are many more things of which Silverlight is capable example being smooth animation. However Javascript/HTML5 offer a lot of very nice animation frameworks as well so the point of this list is just to show how Silverlight differentiates from HTML5. Once again (just to reiterate) I’m not saying Silverlight is NOT better than HTML5 and HTML5 is NOT better than Silverlight. They are very simply, different technologies that have different capabilities. The key is to determine what the requirements are for your application and then make an informed decision based on the facts of what the technological capabilities are for each platform. The key for developers and consumers is choice. We now have more choices than we did before. And not just more of the same, given this list (and the many many features I haven’t listed) Silverlight is much more and this is a good thing for all of us. HTML5 however is also much more than its predecessors and is a very exciting technology to say the least. At the end of the day we cannot ignore technologies that are different because we’re too scared to learn something new. This will only serve to narrow our perspective and make us less than we could be. Its time to understand these technologies and the vacuum that they are trying to fill and why and admitting that those vacuums are real and need to be addressed instead of listening to those who have uninformed opinions such as Dean Wilson. This is a textbook example of ‘A little knowledge is a dangerous thing’.
Let me start out by saying (for all the test driven devs out there who are going to pick this apart lol) that catching bugs through testing is far better than debugging and catching bugs through error logs. However, that does not mean that test driven development has brought Utopia to earth and that any software that implements proper testing doesn’t have bugs. They still have bugs,,, just a lot fewer bugs.
Scenario
So I’ve been working on a windows service as of late that does a lot of database calls, emails etc. So a lot of external things could happen to cause exceptions and I wanted to be able to quickly look up in a log file to see what errors were occuring. Here’s a quick little class to get an exception and ouput a formatted error message that points to where the problem originates:
class ExceptionFormatter { StringBuilder format = new StringBuilder(); public ExceptionFormatter(Exception exception) { StackTrace stacktrace = new StackTrace(exception, true); var stackframes = stacktrace.GetFrames(); format.Append("********* Error ************\r\n"); format.Append("Message: " + exception.Message + "\r\n"); format.Append("Inner Message: " + (exception.InnerException != null ? exception.InnerException.Message : "") + "\r\n"); foreach (StackFrame frame in stackframes) { if (frame.GetFileLineNumber() != 0 && !string.IsNullOrEmpty(frame.GetFileName())) { format.Append("File Name: " + frame.GetFileName() + "\r\n"); format.Append("Line Number: " + frame.GetFileLineNumber() + "\r\n"); format.Append("Column Number: " + frame.GetFileColumnNumber() + "\r\n"); format.Append("Method Name: " + frame.GetMethod() + "\r\n"); } } format.Append("****************************"); } public override string ToString() { return format.ToString(); } }
This is really simple to use. Just pass the exception into the construct and then call the .ToString() method and you get your formatted error. This iterrates through the stackframe to get the location of the errors on top of what the errors are. Hope this helps!
So recently I’ve been playing around with keyloggers. A keylogger is a small application that typically is used for malicious purposes, but they run on your computer and record all key strokes coming in from your keyboard. This works by attaching to a win32 api ‘hook’ called the ‘low level keyboard’ hook. Most programmers have two sides, the ‘programmer’ side and the ‘hacker’ side. This can be very helpful in the long run as the two sides fight against each other and come up with methods to outsmart each other. So I started thinking ‘how can you defend against a keylogger?’. The first and most obvious choice is some kind of antivirus. However, most real hackers write their own unique keyloggers that antivirus doesn’t have in its database. Case in point, I wrote up a quick little key logger and ran it on my computer that has several antivirus programs and none of them picked up on it. Another option is that there are several small applications that have methods of ‘finding’ keyloggers. The method is usually monitoring the file system to see if a file is growing as the user is typing. This works sometimes but not always. Both of these methods are good but if you have an application that needs extra security going out to hundreds of users the risk becomes greater and greater.
A solution
One solution for this problem is to generate a random number of random keystrokes as a user types in each key into say, a password textbox. Now there are several requirements for this to work:
Requirement #1: The random key strokes must be detectable by the keylogger
Requirement #2: The characters must be backed out as they will end up in the textbox the user is typing in
Requirement #3: The backspace must not be detectable by the keylogger
For this solution I used a project called ‘Input Simulator’ (http://inputsimulator.codeplex.com/). This uses the windows api to generate keystrokes that are indistinguishable from a keystroke coming in from the keyboard. To back out the character I programatically fire an event on the password textbox that the user is typing in. Here’s the code:
public Login() { InitializeComponent(); keycodes.Add(VirtualKeyCode.VK_0); keycodes.Add(VirtualKeyCode.VK_1); keycodes.Add(VirtualKeyCode.VK_2); keycodes.Add(VirtualKeyCode.VK_3); keycodes.Add(VirtualKeyCode.VK_4); keycodes.Add(VirtualKeyCode.VK_5); keycodes.Add(VirtualKeyCode.VK_6); keycodes.Add(VirtualKeyCode.VK_7); keycodes.Add(VirtualKeyCode.VK_8); keycodes.Add(VirtualKeyCode.VK_9); keycodes.Add(VirtualKeyCode.VK_A); keycodes.Add(VirtualKeyCode.VK_B); keycodes.Add(VirtualKeyCode.VK_C); keycodes.Add(VirtualKeyCode.VK_D); keycodes.Add(VirtualKeyCode.VK_E); keycodes.Add(VirtualKeyCode.VK_F); keycodes.Add(VirtualKeyCode.VK_G); keycodes.Add(VirtualKeyCode.VK_H); keycodes.Add(VirtualKeyCode.VK_I); keycodes.Add(VirtualKeyCode.VK_J); keycodes.Add(VirtualKeyCode.VK_K); keycodes.Add(VirtualKeyCode.VK_L); keycodes.Add(VirtualKeyCode.VK_M); keycodes.Add(VirtualKeyCode.VK_N); keycodes.Add(VirtualKeyCode.VK_O); keycodes.Add(VirtualKeyCode.VK_P); keycodes.Add(VirtualKeyCode.VK_Q); keycodes.Add(VirtualKeyCode.VK_R); keycodes.Add(VirtualKeyCode.VK_S); keycodes.Add(VirtualKeyCode.VK_T); keycodes.Add(VirtualKeyCode.VK_U); keycodes.Add(VirtualKeyCode.VK_V); keycodes.Add(VirtualKeyCode.VK_W); keycodes.Add(VirtualKeyCode.VK_X); keycodes.Add(VirtualKeyCode.VK_Y); keycodes.Add(VirtualKeyCode.VK_Z); } private void PasswordTextBox_KeyUp(object sender, KeyEventArgs e) { Random RandNumber = new Random(); int RandLength = RandNumber.Next(1, 5); int RandDigit; int RandShift; if (e.Key != System.Windows.Input.Key.Back) { for (int i = 0; i < RandLength; i++) { RandShift = RandNumber.Next(0, 1); if (RandShift == 1) { InputSimulator.SimulateKeyDown(VirtualKeyCode.SHIFT); } RandDigit = RandNumber.Next(0, 36); InputSimulator.SimulateKeyDown(keycodes[RandDigit]); var target = Keyboard.FocusedElement; var routedEvent = Keyboard.KeyDownEvent; KeyEventArgs ev = new KeyEventArgs( InputManager.Current.PrimaryKeyboardDevice, InputManager.Current.PrimaryKeyboardDevice.ActiveSource, 0, Key.Back); ev.RoutedEvent = routedEvent; target.RaiseEvent(ev); if (RandShift == 1) { InputSimulator.SimulateKeyUp(VirtualKeyCode.SHIFT); } } } }
So this little bit of code runs on the keyup event of the password textbox. To make the amount of random characters larger simply change RandNumber.Next(1, 5) to RandNumber.Next(1, 10), but keep in mind that its going to have to back out more characters.
