
Introduction
Most distributed applications need some form of cryptography to protect their passwords from snooping eyes whether they're hackers or simple users. I came to face this sort of problem a little while ago while I was working on one application of my own. I had a program that needed to provide a password to an application, but I didn't want to hardcode the password nor save it as plaintext either in a file or in the registry. I looked around to see how I could "safely" hide the password without the need of another password, and all I found was the DPAPI (Data Protection API) provided by Microsoft. I read the documentation and I thought it was too much and too complex for the "simple" thing I wanted to do, so I decided to do something about it.
Tentative Solution
I knew I could not use a well known cryptographic symmetric algorithm because all of them rely on a password to protect information. I also knew that without a password to protect my password, I would be relying the security on the algorithm. This means that anyone that knows the algorithm will be able to decrypt the byte array and get the original input password.
I decided to take my chances and I developed a DLL that would receive a variable-length input password and give a fixed-length byte array as the output. The result array would always be different and would have some error correction features.
Some Basic Background
When I set my goal to make an algorithm with different but fixed output with some error correction abilities, I started working right away on wondering how I could get this feature solved in the most secure way.
I decided to use two basic techniques for obscuring redundancies in plaintext messages, they are confussion and difussion:
- Confussion obscures the relationships between plaintext and ciphertext.
- Diffusion dissipates the plaintext by spreading it over the ciphertext.
The ingredients to get all this together and working turned out to be a little bit of Datetime.Now.Ticks, some random numbers, an MD5 hash, XOR operations, and an interesting method called chained autokey.
The Algorithm's principal Ingredients
- The
DateTime.Now.Ticks instruction returns a long number, this "unique in time number" represents the number of 100 nanoseconds passed since 12:00 a.m. January 1st, 2001. This 18 digit number is used to assure the uniqueness of the result.
- The random numbers are used to select different locations that will be saved as plaintext chars. They help to create a random header. This is another ingredient to get a different result each time.
- The password's MD5 hash, as well as the
Datetime.Now.Ticks, are used to fill in the spaces needed, and can be retrieved again at the time of decoding, they help accomplish the confussion technique.
- The XOR operation and the autokey method are used to make the diffusion work, to spread the plaintext password into the ciphered result.
Chained Autokey Explained
The idea behind autokey comes from the fact that a key that changes with every message provides more security than one that is used over and over for several messages. In other words, a key that changes with each message is the best deal you can get.
What a better way to ensure this than by using the message itself as the key.
For example:
password: jodelios
charcodes: 6A 6F 64 65 6C 69 6F 73
To encipher:
Autokey XOR 1st operation: Chained Autokey XOR 2nd operation:
6A 6F 64 65 6C 69 6F 73 6B 05 0B 01 09 05 06 1C
6A 6F 64 65 6C 69 6F 73 6B 05 0B 01 09 05 06 1C
-------------------------- --------------------------
6A 05 0B 01 09 05 06 1C 73 6B 6E 0E 0A 08 0C 03 1A 1C
To decipher the idea is pretty much the same thing:
Chained Autokey XOR n-1 operation: Chained Autokey XOR n operation:
6B 6E 0E 0A 08 0C 03 1A 6A 05 0B 01 09 05 06 1C
6B 05 0B 01 09 05 06 1C 6A 6F 64 65 6C 69 6F 73
-------------------------- --------------------------
6B 05 0B 01 09 05 06 1C 6A 6F 64 65 6C 69 6F 73
When encoding or decoding, you should notice that on every round, the first char is retained and the last one is always dropped. When encoding, the first char is incremented for the next round, but when decoding, the first char is decremented. The number of rounds (n) that this operations take place depends on the password length (n). If the password has 10 chars, there will be ten rounds.
Error correction
The error correction idea came to life to fulfill two different objectives. The first was to give the user some backup if the encoded byte array was going to be transferred and/or edited by an external factor, such as another program or even an intruder. The second reason for the existence of error correction scheme was to be able to get a fixed-length random header so that the encoded byte array would always have 64 bytes.
The error correction arrangement is done by picking random 'plaintext' char positions from the final 48 byte block result. I say they are 'plaintext' because nothing is done to the charcode chosen, but they are not really plaintext from the original password block.
The whole algorithm but in brief
To encode:
- Get the password, the ticks, and the MD5 password hash converted to byte arrays.
- Calculate the number of elements from the MD5 hash array and from the ticks array that will be used to fill the spaces needed to complete 48 bytes.
- n Autokey chained XOR rounds are performed.
- A 16 byte random header is created selecting some 'plaintext' positions and their corresponding chars.
- A final XOR round is performed with an expanded version of the random header.
To decode:
- Final XOR round is performed with an expanded version of the random header.
- Header analyzed to do error correction.
- n Autokey chained XOR rounds are performed to obtain the original 48 byte block.
- MD5 hash and ticks dropped if requested.
Final Words
I've explained the most important assets of the algorithm, nevertheless there are still some interesting but hidden characteristics. As I mentioned when I was starting the article, this algorithm is not 100% secure, but I guess I can be of help when developing middle size applications where you need to have several passwords and you want them encrypted. Feel free to modify the algorithm to fill your needs, but if you do so, please do try to contact me or mention my work in the results. Any improvements, errors, comments, anything, don't hesitate to let me know, they'll be appreciated.
History
First time around, will work on further versions depending on the acceptance of the project and its ideas.