I’m Terrible at Coding Assessment Tests

What are coding assessment tests?

A coding assessment test is a programming challenge companies send their prospective new hires to see how much they know about writing software. They are generally an online only environment and is timed. Some popular sites are codesignal.com, codility.com.

A bit about me

I’ve been writing software professionally for about 15 years. I’ve held the title of Senior Developer for around 9 years. And I don’t even hate solving puzzles with code. Somewhere in an old repository I have about 50 problems solved from the site projecteuler.net

Why am I terrible at them?

  • I think my problem is that it isn’t conducive to how I work. When I run into a novel problem in the real world, I tend to either poke at it or just sit with it then walk away. Then I might come up with something to try and poke at it again. Rinse, Repeat. Eventually I come up with a solution that works. Later I’ll likely go back to it, clean it up and make it better. That approach doesn’t really work when you need to solve the problem within a timed test. I generally do get a solution that works, but it’s never one that I’m proud of.
  • They tend to hide the criteria they use to grade your submissions. This feels in bad faith. If I wrote some code at work and was told it was too slow, I would gladly go back and refactor until I got it to a more efficient state. Many times these tests will tell you it works, but not give any information on efficiency. Then after submitting the test it will tell you that your code wasn’t fast enough. Why not tell the test taker that when they have an opportunity to fix it? What real world scenario is like that? There is no logical reason to have performance requirements that are secret.
  • It doesn’t test for things that I think are most important. These assessments can easily test for correctness and performance. They cannot test for readability, cleanliness, or maintainability. Those factors are very valuable to a development team, and are harder to find in new hires.

What should companies do instead of online coding tests?

My preference is to offer prospective hires a medium difficulty take home assignment. It could be a puzzle type question, or it could be an example of a real problem they might run into on the job. You could give them 3 or 4 days to complete it. This gives plenty of time to find better solutions through trial and error. I think companies are worried that the candidates may ask someone else to solve something like this for them. Which could happen, but could mostly be rooted out by asking them to explain their solution and why they went with that approach. If they can confidently explain the code in front of you, and go through their thought process, then it’s likely they actually wrote it.

Final Thoughts

Online coding assessments are a gate that can filter out a lot of bad candidates, but it also filters good candidates who may struggle with the testing format. I’ve always seen software development as an iterative process. Write it once, if it fails, try again, re-write it better, clean it up, make it run faster, do it over and over till you can’t find any other way to make it better. An online test that allots 35 minutes doesn’t allow for that.

Implementing encryption the right way with AES (I think)

Security is something nearly every app has to worry about in some form. There are a ton of incorrect or incomplete implementations around the internet. Unfortunately “good enough” isn’t good enough with this stuff. If it’s done wrong you are probably better off not doing it. I did a ton of reading to find the correct implementation, and I’d like to share it here. All examples are going to be in c# and are comparable with .Net Core. This will probably turn into a series depending on the feedback I get.

First in the series is AES (Advanced Encryption Standard). It is a synchronous encryption cypher, meaning you use the same key to encrypt and decrypt. AES has a few settings that you should know about (and get right)

Aes.Mode = CipherMode.CBC;

You have a few modes to choose from but CBC (Cipher Block Chain) is the one that you should go with. AES carves data up into blocks (128 bits) and encrypts each block at a time. This can be problematic because if you have the same data and the same encryption key then your encrypted data would look the same. This could leak information that commonly repeats. But in CBC mode the cipher adds some data from the previous block and then encrypts it. This helps change the encrypted version even if the underlying text is similar.

Aes.Padding = PaddingMode.PKCS7;

The next setting to talk about is padding. As I said above AES encrypts data in 128 bit blocks. if the last block isn’t 128 bits then what do we pad that block with? There are a few options, like zero’s but PKCS7 pads with the number of empty blocks. For example if the last 4 bytes are padding, the last 4 bytes are populated with 04 04 04 04.

Aes.BlockSize = 128;

As I’ve mentioned already AES encrypts data in 128 bit blocks. I believe this is only editable because the underlying cypher (Rijndael) had a variable block size. Just hard code it to 128.

Aes.KeySize = 256;

The key size can be set to either 128, 192, or 256. With the power of modern devices I don’t see any reason to use anything other than 256. Just a note here 128 isn’t half as good as 256. The way bit math works 255 is half as good as 256. AES 256 has 1 x 10^77 (That’s 1 with 77 zero’s after it) possible keys. AES 128 has 3 x 10^38 possible keys. So AES256 is exponentially stronger than AES128.

Aes.GenerateIV();

The Initialization Vector (IV) is where I see the most confusion, and bad practices. As stated earlier, in CBC mode AES takes some data from the previous block and mixes it into the current block creating a chain that is more scrambled than doing each block on its own. However what do you do with the first block of data? There’s no previous block to mix with. That’s what the IV is. Its a random chunk (16 bytes) of data that is mixed with the first bock before it’s encrypted. This data doesn’t need to be secret, but it does need to be unique. Luckily the AES cipher has a GenerateIV() function built in. however you’ll need that exact same IV in order to properly decrypt. This is why most people just hard code the IV with the same 16 bytes for everything they encrypt/decrypt. That works fine (though is less secure) as long as you aren’t sending the encrypted data to someone else. So what you should do is use the GenerateIV() function, and then append the generated IV to the beginning of the encrypted text. That way when you (or anyone else) are ready to decrypt you have it in the file. I’ll post my full AES implementation at the end of the article and you can see an example.

So all of the above settings are default in AesManaged. I detail them here because you may see implementations of AES in applications you work on. If they are not these settings you should ask why they are different. If there isn’t a good reason for it, you should argue for fixing it.

AES.Key = (encryptionKey);

This is the key you are encrypting with. It has to be a byte[] that is the same length as the KeySize above (again I suggest 256bits). It should be a randomized string of bits, or a hashed password. This key is what you need to keep secret. The encrypted data can be public, the settings used to encrypt can be public, the Initialization Vector can be public, but the Key HAS to be private.

That’s it for settings. The steps to encrypt aren’t too difficult. you set up 2 memory streams. One for input (the data) and one for output (the encrypted data). In between you set up a CryptoStream using the AES object you created.

Here’s a link to a demo implementation (on github) AesSimple