|
|
I’ll continue to develop our application I’ve started last week by refining the layout of the user interface and continue adding more features to it.
First thing I’ll do is to add the keys and scales under the Accordion Panels named Keys and Scales. Here I’ll try to introduce another cool visual feature of Dojo framework, the fisheye. It is a visual effect where, when you hover your mouse over a text or image, it magnifies it, just like a fisheye lens would do, and then bounces it back to its normal size with a nice animation. I thought this could be a nice way of emphasising the Key and Scale names without over-cluttering the panel.
To do this, I’ll start by including the Fisheye Widget library
dojo.require("dojox.widget.FisheyeLite");
I also need to add a function to turn list items into Fisheye items when the page loads
dojo.addOnLoad(function(){
// Turn li's in this page into fisheye items
dojo.query("li.bounce", dojo.byId("fishEyeList")).forEach(function(n){
new dojox.widget.FisheyeLite({ },n);
});
dojo.query("li.bounce", dojo.byId("fishEyeList2")).forEach(function(n){
new dojox.widget.FisheyeLite({ },n);
});
});
After that, all I need to do is to change the contents of the accordion panel with the appropriate list items:
<div dojoType="dijit.layout.AccordionPane" title="Keys" id="fishEyeList">
<ul>
<li class="bounce"><span class="fisheyeTarget">C</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">D-flat</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">E</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">E-flat</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">F</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">G-flat</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">G</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">A-flat</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">A</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">B-flat</span><hr></li>
<li class="bounce"><span class="fisheyeTarget">B</span><hr></li>
</ul>
</div>
Now I should be able to go and see if the fisheye effect really works. For now I wrote down the scale and key names in an ugly way, i.e. E-flat, etc., instead of using the proper conventional musical signs. I’ll probably do that later as it requires some art work. Even with the text only version it looks much better than before:
 Fisheye List
Next, I’ll add some content to the top section of right panel to instruct the user how to use the application. At the bottom, I’ll have the tabbed pane to show different views of the scale, etc. as per our initial design. The instruction text is simply static HTML for now, but when the application is wired up, certain parts of this text should change dynamically. The place holder text looks like this:
<h1>Chart Viewer</h1>
<h3>You are currently viewing C Major Scale</h3>
<p>
Change Keys on the left panel to transpose this chart to another key.
<p>
Choose other Scales and Chords on the left panel to highlight the notes of these scales and charts below.<br>
<p>
At the bottom, I fill in the tabbed pane windows (only two for now) with some content. I’ll start with the easiest one to implement, a simple table of degrees and the corresponding notes at the bottom:
<div id="mainTabContainer" dojoType="dijit.layout.TabContainer" style="width:98%;height:100%;">
<div id="Table" dojoType="dijit.layout.ContentPane" title="Table View" selected="true">
<p>
<table border="1" width="100%" id="chordTable">
<tr>
<td width="16%">Degree</td>
<td width="7%">I</td>
<td width="7%">IIb</td>
<td width="7%">II</td>
<td width="7%">IIIb</td>
<td width="7%">III</td>
<td width="7%">IV</td>
<td width="7%">Vb</td>
<td width="7%">V</td>
<td width="7%">VIb</td>
<td width="7%">VI</td>
<td width="7%">VIIb</td>
<td width="7%">VII</td>
</tr>
<tr>
<td>Note</td>
<td>C</td>
<td>Db</td>
<td>D</td>
<td>Eb</td>
<td>E</td>
<td>F</td>
<td>Gb</td>
<td>G</td>
<td>Ab</td>
<td>A</td>
<td>Bb</td>
<td>B</td>
</tr>
</table>
</div>
<div id="NotationView" dojoType="dijit.layout.ContentPane"
title="Notation View">
Coming Soon...
</div>
</div>
And now the whole right panel should look something like this:
 Right Panel
It doesn’t do much at the moment, but note that the chart table dynamically adjusts its width when the panel size is changed. Experiment by changing the overall browser window size, as well as changing the relative sizes of the left panel and the right panel. All contents should look good regardless of the panel sizes and the layout manager should be doing its job to keep the nested panels in proper dimensions as the height and width of parent containers change.
A working DEMO of the application is provided here:
http://karul.org/etc/mhelper/mhelper2.html
Next time I’ll start implementing some core functionality, so our application will start doing something useful.
Some of the concepts discussed in this Blog has over the time evolved into an application you might want to check out:
http://music.isallicare.com
Thanks for visiting my Blog — C. Karul Jan 3, 2010
If you have ever attempted to write software that has a GUI (Graphical User Interface), you’ve probably noticed that creating both intuitive and functional user interface is a lot harder than it looks. A number of different skills are required to design a good user interface, skills often hard to find in one person. Although I did create a lot of applications with GUIs using different technologies, I don’t necessarily see myself as an expert in this field. The contents of this blog are derived from the somewhat sketchy notes I took while I was experimenting with the Dojo Layout Manager; and then during my attempt to write a simple application to help musicians learn and practice keys, scales and chords.
I don’t intend to repeat any information that is already available on the Dojo web site. I’ll instead try to document the quirks and non-typical behaviors I noticed during my experimentation, provide some code snippets and the describe the workarounds I was able to come up with, to help you (and me) save time in your next project.
A layout manager is a specialized piece of code that provides a hierarchical layered container structure and dynamically changes the screen layout so that the user can alter her/his experience by adjusting the size of the screen, and/or various components on the screen to her/his liking. This can somewhat be achieved using standard HTML and CSS in a creative way, but pulling this off is no easy feat, and is often very time consuming for your average developer who may also lack the artistic skills required to do it. A layout manager, on the other hand, abstracts the complex logic behind the interactions between graphical objects and provides the developer a high level API (Application Programming Interface) that makes their job significantly easier.
I’ll start with what I normally do when I need to design and implement GUIs: start sketching a diagram on a piece of paper and decide on:
- what kind of components will I need on my screen?
- which components will be fixed size, which will dynamically change size and in what direction?
- what will I put in these components?
The following diagram contains my 5 minute back-of the-napkin design.

I cannot emphasise enough the importance of spending 5 minutes to draw out your initial design on a piece of paper before you ever touch the computer. It will save you from hours of unnecessary work down the road. I drew this picture by just visualizing how I think an easy to use interface could look like, without considering any technical aspects of it. I’ll now try to map the visual components into actual visual objects. My design essentially is composed of three different components:
- The Top Panel, which will contain the title, buttons, menus, etc; if I decide to have any
- The Left Panel, which will contain what is called an Accordion Menu system (similar to what you have on Microsoft Outlook) that will hold different elements of musical harmony, such as keys, chords, etc. Under each panel I’ll have a list of these elements.
- The Right Panel, which will contain the content, the scale/chord charts.
The top panel will be fixed size. Left and right panels will be as tall as the screen, and their combined width will be as wide as the screen as well. The entire application should fit into the browser screen, regardless of how big or small it is. The user will be able to adjust the relative widths of the left and the right panels.
So if I make a hierarchical list of what will go into my panels it will look something like this:
Application
Top Panel (Title, buttons, etc.)
Left Panel
Keys
Scales
etc...
Right Panel
Information, buttons to print, etc.
Different views of keys, scales, etc. (one at a time)
Table view
Notation view
Piano keyboard view
Guitar keyboard view
Magic Circle View
etc...
Now all I need to do is to transfer this structure into the appropriate HTML code with references to appropriate Dojo Layout objects.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3.2/dojo/dojo.xd.js" djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dijit.layout.SplitContainer");
dojo.require("dijit.layout.LayoutContainer");
dojo.require("dijit.layout.AccordionContainer");
dojo.require("dojox.layout.ContentPane");
dojo.require("dijit.Toolbar");
dojo.require("dojo.parser"); // scan page for widgets and instantiate them
dojo.require("dijit.layout.TabContainer");
</script>
<style type="text/css">
@import "http://ajax.googleapis.com/ajax/libs/dojo/1.3.2/dojo/resources/dojo.css";
@import "http://ajax.googleapis.com/ajax/libs/dojo/1.3.2/dijit/themes/tundra/tundra.css";
@import url("mhelper1.css");
</style>
</head>
<body class=tundra>
<div dojoType="dijit.layout.LayoutContainer" id="mainDiv">
<div dojoType="dijit.Toolbar" layoutAlign="top" id="topPanel">
<span id="title">Title</span>
</div>
<div dojoType="dijit.layout.SplitContainer" orientation="horizontal" layoutAlign="client">
<div dojoType="dijit.layout.AccordionContainer">
<div dojoType="dijit.layout.AccordionPane" title="Keys">
<ul>
<li>C</li>
<li>D-flat</li>
<li>D</li>
<li>....</li>
</ul>
</div>
<div dojoType="dijit.layout.AccordionPane" title="Scales">
<ul>
<li>Major</li>
<li>Minor</li>
<li>Diminished</li>
<li>....</li>
</ul>
</div>
</div>
<div dojoType="dijit.layout.ContentPane" title="Chart Viewer" style="padding:5px;">
Information, buttons, etc which are common about the different views keys, scales, chords, etc...
<div id="mainTabContainer" dojoType="dijit.layout.TabContainer">
<div id="Table" dojoType="dijit.layout.ContentPane" title="Table View" selected="true">
Table view goes here...
</div>
<div id="NotationView" dojoType="dijit.layout.ContentPane"
title="Notation View">
Notation view goes here...
</div>
</div>
</div>
</div>
</div>
</body>
</html>
When you save this HTML code in a file and open it with a Web Browser it will look something like this:

If you are using Firefox 3.0, you’ll probably end up with an empty screen, which happened to me first time I tried. This annoying problem occurs when you don’t explicity set a size for the <html> and <body> tags, which is apparently a Firefox bug not very well documented by Dojo developers. Interesting enough, it works just fine for Microsoft Internet Explorer and Google Chrome as well as earlier versions of Firefox. To workaround this problem, you need to define a style sheet which provides sizes for html. body and mainDiv style elements:
body {
width: 100%; height: 100%;
border: 0; padding: 0; margin: 0;
align: center;
}
html {
width: 100%; height: 100%;
background-color: #EEE;
}
#mainDiv {
width: 95%;
height: 98%;
border: 0;
padding: 0;
margin: 0;
background-color: white;
margin-left:auto;
margin-right:auto;
}
You can copy and paste the CSS snippet above into a file named mhelper1.css and place it at the same folder as your html file, and it should work.
As you can see in the screenshot above that there is another problem with the tabbed pane panel, which is slightly bigger than the panel it is placed in. The Layout Manager somehow fails to adjust the size of the child panel for some reason. I’ll tackle with this problem and keep improving our simple application another time.
For a working DEMO (version 1) of this application visit:
http://karul.org/etc/mhelper/mhelper1.html
Some of the concepts discussed in this Blog has over the time evolved into an application you might want to check out:
http://music.isallicare.com
Thanks for visiting my Blog — C. Karul Jan 3, 2010
Now that we know how to calculate the number of operations we need for each type of password, and have a tool to experiement with, let’s calculate how long will it take for a modern computer to break passwords of different strengths. This is a bit tricky as computers have different calculating powers, multiple processors, and a tendency to double their performance every two years (See Moore’s Rule). There is also the super computers that have thousands of CPUs running in parallel, like those used by CERN and NSA. It is highly unlikely that someone is going to waste a supercomputer’s time to break your Facebook password, so for our experimentation’s sake we can stick with a typical PC with a dual core @2.1GHx CPU. As the act of trying hashes is a very linear process, we can safely assume that it will take a supercomputer a known fraction of (say a one in a thousand) what our PC will spend.
Let’s start with running the simple Java class (PasswordStrengthDemo.java) I have developed in my last blog entry. At this point the class is hard-wired to run to find a pre-determined hash value, the one I used in one of the earlier blog entries: 098f6bcd4621d373cade4e832627b4f6. If we run the class (I assume you know how to do that), it will run for a while and spit out a long log on the console:
...
tesj --> b117d3a49b25fe3779a6f261002a0625
tesk --> 077c4820ecb9b6304d978aaf2c8e392f
tesl --> d83ed9e1968b5d2dee3aa077a1a23c82
tesm --> 4a6e9c37340f49cbb49c2308baeb1f04
tesn --> dfcf36a673b960b2923b6b3391c46d57
teso --> 9209547629510388c4bd8895f6f09cd5
tesp --> e6c2f934a35941a13fd3a0305085ae8a
tesq --> 25fc24b37d03f5f19c3bdebaf44758be
tesr --> 171741cb32a4a8887a82befac1877d9b
tess --> 8b8be2799a2796a36a02004608426bdb
test --> 098f6bcd4621d373cade4e832627b4f6
The password is test
Processed 2683324 words in 78172 milliseconds.
To refresh your memory, our application has generated and tested every single combination of 4 lettered words using an alphabet of both upper and lower case letters, until eventually it figured out the original password, the hash of which was provided as an argument. This type of attack is called a brute-force attack. It took my laptop 78 seconds to reach the result, which is a little bit more than a minute. To make it more interesting to watch, I printed out every word –> hash combination, which in real life is never done (despite what Hollywood movies suggest) because I/O operations (such as writing to a console or file) degrades performance significantly. I’ll now comment out the line of code which prints this information
...
byte[] input = inputStr.getBytes();
String hashed = hash(input, 0).toString();
// If you want to see each calculated hash, uncomment the next line.
// Note however that this will slow down the performance.
//System.out.println(inputStr + " --> " + hashed);
counter++;
if (hashed.equals(knownHash)) {
...
and run the application again to compare the performance difference. After running for a while quitely, our application now processed the same amount of words (2,683,324) in about 1/8th the time.
The password is test
Processed 2683324 words in 10089 milliseconds.
That’s why I’ll run the application in quiet mode from now on to get more representative performance numbers.
To start our experiments I’ll make two more changes to the code: 1. I’ll change the passed hash argument value to an empty string, so the application will run all the way to the end and won’t stop when it finds the correct password.
// This is the hash for the word "test"
tester.run("");
2. I’ll alternate between different alphabets, and try to figure out the average time needed to test one combination. We’ll start with the simplest alphabet, numbers only, and then incrementially increase alphabet size.
// Numbers only
String[] alphabet = new String[] {
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
};
When we run the code for the numbers-only alphabet, we get our result in the fraction of a second:
Could not find the password!
Processed 10000 words in 146 milliseconds.
Now we try it for lowercase Letters. It takes more than 10 times longer, but it still takes less than two seconds to break a 4 lettered all lowercase password.
Could not find the password!
Processed 456976 words in 1769 milliseconds.
This time we use the alphabet that contains both the lower and upper case letters.
Could not find the password!
Processed 7311616 words in 26754 milliseconds.
For upper/lower letters and numbers combined
Could not find the password!
Processed 14776336 words in 56785 milliseconds.
When we use an alphabet that contains all upper/lower letters, numbers and special characters combined, an ordinary PC can break any 4 lettered password in less than 5 minutes.
Could not find the password!
Processed 74805201 words in 274211 milliseconds.
So a 4 lettered password is never safe, no matter what your key space (or alphabet) is.
We now can calculate how long it takes an average computer to try out one word. We simply divide 274,211 by 74,805,201 to find the time needed to process a single word, which is 0.00366 milliseconds. I’ll calculate it again with another alphabet to make sure that the numbers add up: 56,785 divided by 14,776,336 is 0.00384, which is close enough to 0.00366. We can round this number up to 0.004 milliseconds per word and use it to calculate how long it takes to break passwords of different strengths.
The following table summarizes various passwords and how long will an ordinary computer would spend to find the right combination with a brute-force attack. Note that measured values are black and calculated (estimated) values are in red.
| Password |
Key Size |
Key Space |
# Combinations |
Time to break |
| 4 digit numbers |
4 |
10 |
10,000 |
0.14 seconds |
| 4 letter word – lowercase |
4 |
26 |
456,976 |
1.77 seconds |
| 4 letter word – upper/lower case |
4 |
52 |
7,311,616 |
26.75 seconds |
| 4 letter word – upper/lower/numbers |
4 |
62 |
14,776,336 |
56.79 seconds |
| 4 letter word – upper/lower/numbers/special chars. |
4 |
93 |
74,805,201 |
4.5 minutes |
| 6 digit numbers |
6 |
10 |
1,000,000 |
4.0 seconds |
| 6 letter word – all lowercase |
6 |
26 |
309,915,776 |
20.6 minutes |
| 6 letter word – upper/lower case |
6 |
52 |
19.7 billions |
22 hours |
| 6 letter word – upper/lower/numbers/special chars. |
6 |
93 |
647 billions |
30 days
|
| 8 letter word – upper/lower/numbers/special chars. |
8 |
93 |
5.6 million billions |
710 years |
| 10 letter word – upper/lower/numbers/special chars. |
10 |
93 |
48 billion billions |
6.1 million years
|
| 12 letter word – upper/lower/numbers/special chars. |
12 |
93 |
4.2×10^23 |
53 billion years
|
The comparison table says it all: By just choosing a 8 lettered password which contains at least one number, an uppercase letter, a lower case letter and a special character you make your password practically unbreakable. Just adding 4 more letters to your password will make it impossible to break 4 times the age of the universe.
Keep in mind that you don’t have to choose a weird password you are guaranteed to forget in a week to make it secure. Most people use a little trick that makes a password both hard to break and easy to remember at the same time. Just pick a word that is not too short, and preferably not in dictionary. Combining two different words that do not normally come together in a dictionary is a good way to do this. For example:
MyFirstDate
HappyDog
iLoveMyPorsche
Make sure at least one letter is capitalized as I did above. Then switch certain letters in the words with look-alike numbers, (i.e. 0 for O, 1 for l, 5 for s, etc.)
MyF1rstDate
HappyD0g
1L0veMyP0rsche
and add a puctiation mark somewhere you can remember
My~F1rstDate
HappyD0g
1L0veMyP0rsche!
Just don’t be too obvious, because someone who knows you well might guess how much you love your Porsche. If you keep your password at least 8 characters long, you can rest assured that it won’t be cracked any time soon.
To perform a brute-force attack on a password, one needs to generate words for every possible combination of letters one by one, and then calculate the hash of each generated word to see if it matches the hash of the password in hand.
To demonstrate the basics of how attackers try to get a hold of your password, I’ll improve the Java Class we used in our earlier blog entry here and turn it into a simple tool to brute force attack passwords.
We’ll start defining a variable called alphabet, which is a String array that holds an array of all valid characters in our alphabet. To try out the effect of changing our alphabet, I have created different versions of this variable, one of which should be active at any given time where all the others are commented out.
The first one is a numbers only alphabet, which we talked about in our last blog:
String[] alphabet = new String[] {
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
};
So if we are working on a password (such as an ATM code), we can use this alphabet that has only 10 members.
In real life, the alphabet is more likely to look something like this:
String[] alphabet = new String[] {
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
"k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
"u", "v", "w", "x", "y", "z",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y", "Z",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"`", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")",
"-", "_", "=", "+", "[", "]", "{", "}", ";", ":", "'", "<",
">", ",", ".", "?", "/", "|", "\\"
};
which contains all numbers, upper and lower case letters and a number of special characters that are allowed in a typical password. In the source code you’ll see other alphabets, which have complexities that range somewhere between the above two extremes. You can essentially create an alphabet of any size, such as one with two members, 0 and 1.
We’ll continue to use the hash method we have developed before:
public String hash(byte[] in, int mode) {
MessageDigest md = null;
byte[] digest = null;
Hex hex = new Hex();
try {
if (mode == 0) {
md = MessageDigest.getInstance("MD5");
}
else {
md = MessageDigest.getInstance("SHA-1")
}
}
catch (Exception e) {
System.out.println(e);
}
digest = md.digest(in);
return new String(hex.encode(digest));
}
}
Now we’ll have to write a simple iterator, which basically creates all possible combinations of letters for a given alphabet. To keep it simple, I’ll make it handle only 4 letter words. Ideally this should be a recursive function that goes as deep as it needs to, but this should do the job to demonstrate the basics.
Note that this function is passed an integer array (int[]) that contains the current positions of each character. Initially it is all zeros, i.e. (0,0,0,0). Also passed is the maximum size for any digit, which is the size of each alphabet – 1.
private boolean increment(int[] digits, int maxSize) {
int curVal3 = digits[3];
int curVal2 = digits[2];
int curVal1 = digits[1];
int curVal0 = digits[0];
if (curVal3 < maxSize) {
digits[3] = curVal3 + 1;
}
else {
digits[3] = 0;
if (curVal2 < maxSize) {
digits[2] = curVal2 + 1;
}
else {
digits[2] = 0;
if (curVal1 < maxSize) {
digits[1] = curVal1 + 1;
}
else {
digits[1] = 0;
if (curVal0 < maxSize) {
digits[0] = curVal0 + 1;
}
else {
return true;
}
}
}
}
return false;
}
Now let’s write the method, where all the magic happens. The method, I called run accepts the knownHash for a password. This is the hash of the password we are trying to figure out.
public Map run(String knownHash) {
we initialize the digit counter, and some other variables.
int[] counterDigits = new int[] {0,0,0,0};
int counter = 0;
Date start = new Date();
… and start an infinite loop, which will stop whenever we reach our goal, or all combinations are tried out with no success.
while (true) {
Here we are simply creating the “word” that is composed of each letter combination of the alphaber, one at a time
String inputStr = (alphabet[counterDigits[0]] +
alphabet[counterDigits[1]] +
alphabet[counterDigits[2]] +
alphabet[counterDigits[3]]
);
We then hash the generated word
byte[] input = inputStr.getBytes();
String hashed = hash(input, 0).toString();
System.out.println(inputStr + " --> " + hashed);
counter++;
Testing if generated hash matches the knownHash. If it does, congratulations you’ve just hacked your first password.
if (hashed.equals(knownHash)) {
System.out.println("The password is " + inputStr);
break;
}
Our increment method will return false if all combinations are tried, after which we simply quit.
if (increment(counterDigits, alphabet.length-1)) {
System.out.println("Could not find the password!");
break;
}
We calculate the time elapsed during the execution and show a small report to the user.
Date end = new Date();
System.out.println("Processed " + counter + " words in " +
(end.getTime() - start.getTime()) + " milliseconds.");
return rawData;
and that’s pretty much it. You can find the full source code for this class here. Next time we’ll start playing with it to better understand how strong passwords work.
A while back I wrote about cryptographic hash functions and how they are used to authenticate people with a password. Today I’ll try to go over common ways of attacking passwords in an effort to help you choose better passwords, yet still be able remember them when you need to.
As this text got bigger than I planned for, I’ll split the article into three parts. The first will cover the basics, second part will walk you through a simple Java application to demonstrate a simple brute-force attack, and the third part will use the said application to demonstrate how our password selection affects the effort needed to break them. If you are not a software developer, you might want to skip the second part but Part 1 and Part 3 should still be a relatively a non-technical read I hope you’ll enjoy.
If you remember from my earlier blog entry, cryptographic hashes are one-way functions. They take an arbitrary sized string of characters (i.e. letters, numbers, punctuation marks, etc.) and convert them into another string of characters (which is just fancy was of saying a word). Their unique ability to allow for easy one-way conversion, while making it very hard (or impossible) to go the other way is what makes them useful. You might wonder, if anyone can make this one way conversion easily, then how come keeping the hash of a secret password is deemed safe? The trick is, as the attacker cannot reverse the hash function to find out your original password (at least in theory), they have to try out every single combination of letters to find a word, which has the same hash as yours. What makes this a method to secure your password is the deterrence factor behind the immense amount of work required to perform these operations and the time required to do it.
Let’s start with a simple case, such as an ATM machine where 4 digit numbers are often as complex as a password can get.
One has to choose their password from a set of 10,000 possibilities, which are essentially numbers (i.e. integers) 0 through 9999:
0000
0001
0002
...
9999
We can actually calculate the number of combinations that can be derived using an n lettered alphabet to create an m lettered word as:
nm
In our 4 digit number password this becomes 104, where 10 is the number of characters you can use (i.e. 0,1,2…9) and 4 is the number of digits one can use to form passwords.
104 = 10,000
Here we assume that the password has to be exactly 4 digits long, which holds true for the ATM case. If we needed to calculate all combinations for 1, 2, 3 and 4 digit numbers, then we would have to add each combination possibility:
101 + 102 + 103 + 104 = 10 + 100 + 1,000 + 10,000 = 11,110
If we increase the number of digits, say to 6, we suddenly make our password 100 times harder for the attacker to break, who now needs to try a maximum of a million different combinations:
000000
000001
000002
...
999999
or
106 = 1,000,000
To try all 1,000,00 possible combinations for modern computer is still no big feat though. If you are wondering, how come banks are still using these simple passwords to protect your hard earned money, software systems have other layers of security where they count the number of logon attempts. If someone fails to logon after a number of unsuccessful attempts (often 3), their account is temporarily locked. So an attacker will not have the chance to try all possible combinations (not in a reasonable amount of time). This, however doesn’t help at all if someone has access to the hashed versions of the password at the bank’s computer system. Although this information is quite hard to get to, it is not uncommon for an insider (such as a disgruntled employee) to sneak it out.
Luckily, almost any software application lets the user choose an alphanumeric (i.e. letters and numbers) password.
Let’s assume the user got lazy and picked a simple password which is composed of all lowercase letters. He can create a large number of 6 lettered passwords using any combination of 26 letters:
a,b,c,.....,z
We can calculate how many different words an attacker needs to try, if s/he attempts to calculate the hashes for each possible combination of letters, (a.k.a. brute-force attacks the password):
aaaaaa
aaaaab
aaaaac
...
zzzzzz
Now that we have our formula, we can calculate the number of possible combinations as:
266 = 308,915,776
If you have noticed, by just using lowercase letters instead of numbers, we made our password 300 times harder to break.
Let’s stay here for a while to talk about another common way of attacking passwords, the so called dictionary attack. Most people have the habit of choosing a simple word for their password. This is understandable, because it is easy to forget passwords, and the name of your dog or brand of your car makes the perfect choice to remember it.
Password attackers know this very well and instead of trying all possible combination of letters, they start trying with meaningful words, i.e. the words listed in a dictionary (hence the name dictionary attack). Such dictionaries often include a large list of all commonly used or previously known passwords as well (such as test, 123456, 0000, etc.).
In the English language there are over 120,000 words and it is quite easy to find one of the many multilingual dictionaries on the Internet. That is still some work, but compared to a brute-force attack, it is a piece of cake for a modern computer.
So never ever select an all-lowecase password that is a dictionary word or a commonly used phrase.
There are also other tricks to make your password even harder to break, some of which you might have probably encountered before. For instance, using both uppercase and lowercase letters in your password will make it a lot harder to break. How hard? let’s calculate:
There are 52 letters in total (26 lowercase and 26 uppercase). If you have picked a 6 letter password that has at least one uppercase letter, you just made the dictionary attack useless (see my earlier blog entry to see why hashes of test and Test are entirely different).
Therefore the only way to find a matching hash with your password is to try out a maximum of
526 = 19,770,609,664
combinations. That is over 19 billion different combinations, versus just over a hundred thousand if you’d chose a dictionary word, or 300 million combinations if you used any non-dictionary lowercase word.
If you want to make your password even harder to break, use at least one uppercase letter, a number and a special character. There are about 100 characters that can be used to create a password. Using at least one of each will force the attacker to try them all:
1006= 1,000,000,000,000
that is a thousand billions.
You can choose a password with 12 characters, which can only be broken after trying
10012 = 1,000,000,000,000,000,000,000,000
combinations, which is equal to 1024.
Next time I’ll write a simple Java class to demonstrate how a password can be brute-force attacked and then we’ll play with the application to see how much time is needed to break passwords of different strengths.
If you are a web developer, JavaScript is a two edged sword. Very few like to use it, yet in many cases you simply cannot avoid it simply because there is nothing out there to replace it. With the popularization of AJAX (Asynchronous JavaScript and XML), JavaScript seemed to be gaining some traction again in the recent years, however it still is a hard to write serious code with it simply because it is not object oriented, hard to debug and has very little out of the box functionality, especially on the visual user interface development area.
Or maybe I should have said it was a hard language to work with. A couple of weeks ago I bumped into the Dojo Toolkit (http://www.dojotoolkit.org/) and I am impressed with what they have done with the Java Script technology. To evaluate how well the technology works, I quickly put together a simple application which turns out to be a simple color picker.
You might think why on earth would anyone need yet another color picker, but I find myself calculating the hexadecimal HTML color codes from RGB numbers every now and then. I also had to keep my 6 year old son busy while working on this, so I preferred to make something that he can enjoy and play with to see how colors mix together.
 Color Picker
Click on the image above to go to the working version of the application at http://karul.org/etc/colorpicker.php.
For most part, coding with Dojo Toolkit is quite painless, especially because all of the required libraries and the style sheets can be referenced as remote URLs. Simply copy the following stylesheet and javascript references in your HTML head and you are good to go.
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css";
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js" djConfig="parseOnLoad: true">
</script>
Both AOL and Google provide free hosting services to these libraries, but you can also choose to download and host them locally.
You start declaring the dojo functions you intend to use
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.Slider");
dojo.require("dijit.form.ValidationTextBox");
...
and add other functions you want to use in your application. In my case I needed to write two functions, one to calculate and update the hexadecimal code on the page
// Calculate and update the hexadecimal code
function updateHex(){
var hexchars = new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
// Read each slider's value into a variable
var r = dojo.byId('slider1input').value;
var g = dojo.byId('slider2input').value;
var b = dojo.byId('slider3input').value;
// Calculate hexadecimal digits (1st and 16th)
var r_16th = Math.floor(r/16);
var r_1st = r - 16*(r_16th);
var g_16th = Math.floor(g/16);
var g_1st = g - 16*(g_16th);
var b_16th = Math.floor(b/16);
var b_1st = b - 16*(b_16th);
// Put it all together to create the code
var hexcode = String('#' + hexchars[r_16th] + '' + hexchars[r_1st] +
hexchars[g_16th] + '' + hexchars[g_1st] +
hexchars[b_16th] + '' + hexchars[b_1st] );
//console.log(hexcode);
// Update the visible hex value
dojo.byId('hexinput').value=hexcode;
// Update the color in the colorPanel
document.getElementById('colorPanel').style.backgroundColor =hexcode;
}
and another one to initialize (reset) everything back to their initial states.
function initialize(){
dojo.byId('slider1input').value = 0;
dojo.byId('slider2input').value = 0;
dojo.byId('slider3input').value = 0;
dojo.byId('hexinput').value='#000000';
dojo.byId('colorPanel').style.backgroundColor = "black";
// Note that I used dijit.byId and not dojo.byId!
dijit.byId('horizontalSlider1').setValue(0);
dijit.byId('horizontalSlider2').setValue(0);
dijit.byId('horizontalSlider3').setValue(0);
}
One thing that took me a while to figure out was the fact that dojo.byId function returns the reference to the HTML view of the Slider and not to the actual object. After unsuccessfully trying to call the .setValue() method of the HorizontalSlider widget, I finally realized that one should use the dijit.byId function to get to the actual object. So if you make a mistake and call
dojo.byId('horizontalSlider3').setValue(0);
It won’t work and you’ll get this exception:
dojo.byId("horizontalSlider3").setValue is not a function
console.log(dojo.byId('horizontalSlider3').setValue(0));
So to activate the methods on dijit widgets, remember to use the dijit.byId function and not the dojo.byId function.
Once the scripting part is over, all you have to do is to insert the widgets into the HTML code. Other than defining a dojoType property for the DIV tag, there is nothing extraordinary here. Note that each widget comes with a number of properties you can configure, such as value, minimum, maximum, etc in this case for HorizontalSlider.
<div id="horizontalSlider1" dojoType="dijit.form.HorizontalSlider"
value="0" minimum="0" maximum="255" discreteValues="256"
intermediateChanges="true"
showButtons="true"
onChange="dojo.byId('slider1input').value=arguments[0]; updateHex();">
</div>
And that’s pretty much it. Note that some parts of the code was omitted for brevity. Dojo has very good online documentation and an active group of supporters. Refer to the following links for more information:
Hash functions are one of the fundamental components of modern cryptography, so I thought it might be a good place to start talking about more advanced concepts.
A hash function is a mathematical procedure that converts arbitrarily length data into fixed size binary strings.
For example:
| “” (empty string) |
d41d8cd98f00b204e9800998ecf8427e |
| “test” |
098f6bcd4621d373cade4e832627b4f6 |
| “A really long text to demonstrate the fact that the output size is always the same regardless of the input size” |
e0e6468a57dcd548dd68f34cc9191cf9 |
You can hash a 2GB file, and the result will still be a 32 digit hexadecimal string (or binary data equivalent to it). The values that are listed in the right column of the table above are called hash-values. Mathematically speaking, they are the y values in the f(x) = y equation, where f is a hash function and x is any arbitrary value.
Now that we know what hashed strings look like, let’s find out why we use them.
A good hash function have some important properties:
1) The probability of a randomly selected string get mapped with a specific hash-value is 2-n, where n is the bit size of the hash-value.
2) It is computationally efficient to calculate the hash-value, however it is computationally infeasible to find two distinct inputs which hash the same value (i.e. collisions).
3) Similar inputs generate non-similar outputs
For example
Test --> 0cbc6611f5540bd0809a388dc95a615b
test --> 098f6bcd4621d373cade4e832627b4f6
Even though I merely changed the upper case T to a lower case t, the two hash-values are entirely different and it is impossible to guess that the input values were actually very similar.
As I’ve described above, an infinite number of possibilities are mapped into a finite number of possibilities. Even though the collisions are unavoidable this is often acceptable because the probability of this to happen is only 2-128, which is practically zero Unlike encryption algorithms, once data is hashed, there is no returning back and the original text cannot be recovered again.
Let’s have a look at the code I used to calculate these examples. It is a very simple java code that reads a text and spits out the hash for it (I marked the most important two lines with red).
import java.security.MessageDigest;
/**
* @author Cuneyt Karul
*
* Example program to demostrate the cryptographic hash functions.
*
*
*/
public class HashExample {
public static void main(String[] args) {
HashExample tester = new HashExample();
tester.run("test");
}
public void run(String inputStr) {
byte[] input = inputStr.getBytes();
String hashed = hash(input).toString();
System.out.println(inputStr + " --> " + hashed);
}
public String hash(byte[] input) {
MessageDigest md = null;
byte[] digest = null;
try {
md = MessageDigest.getInstance("MD5");
//md = MessageDigest.getInstance("SHA-1");
} catch (Exception e) {
System.out.println(e);
}
digest = md.digest(input);
return byteArrayToHexString(digest);
}
static String byteArrayToHexString(byte in[]) {
byte ch = 0x00;
int i = 0;
if (in == null || in.length <= 0) return null;
String digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8",
"9", "a", "b", "c", "d", "e", "f"};
StringBuffer out = new StringBuffer(in.length * 2);
while (i < in.length) {
ch = (byte) (in[i] & 0xF0);
ch = (byte) (ch >>> 4);
ch = (byte) (ch & 0x0F);
out.append(digits[ (int) ch]);
ch = (byte) (in[i] & 0x0F);
out.append(digits[ (int) ch]);
i++;
}
return new String(out);
}
}
If you have noticed, I am using a MD5 hash algorithm which is one of the most commonly used hash algorithms today. It has a hash-value size of 128 bits, which means that there are 2 128 different possible outcomes (roughly equal to 3.4×1038). To put this number in perspective, less than 4.7×1020 milliseconds have passed since the Big Bang (15 billionx365x24x60x60x1000). It is therefore practically impossible for any computer known today or likely to be invented in the near future to try all possible combination of hash-value possibilities to find a collision.
There are however some recent studies which suggest that the MD5 algorithm can be attacked with much less computing power and should not be used any more. Although the danger is not big enough to pose a serious vulnerability today, most modern cryptography systems use SHA-1 and other higher hash size algorithms. A complete list of all supported hash (MessageDigest) algorithms in Java 1.5 can be found here.
Hashes are great tools to confirm that some information has not been not altered without the need to re-process the entire information again. There are often two main reasons to do that:
1) The information is too big and reprocessing it every single time is not efficient.
2) The information is confidental, we don’t want to expose it, yet we want to verify that it was not altered.
Simpler forms of hashes are commonly used outside of cryptography, for such purposes as indexing larger objects and for data integrity verification. For example, file systems calculate hashes for each file and keep a tiny signature to verify that the file has not been modified or corrupted. Network protocols use a similar mechanism to ensure that a sent package reached its destination intact.
Higher strength hashes are the core of almost all password authentication systems in use today. When you enter your password to any application on your desktop or on some online service, the authentication system uses hashes to match your password with what they have in storage. It is considered a very big security risk to keep a clear text copies of user passwords (although I have seen it done!). So almost all authentication systems just keep the hashed version of your password.
Say your password is pumpkin
pumpkin –> edf8377563f7fa2897df6aa434ad305e
The authentication system will save your password hash as edf8377563f7fa2897df6aa434ad305e.
When you enter your password on the logon prompt, the server will immediately recalculate the hash of it and compare it to what it has in storage. Let’s assume you typed Pumpkin with a capital P
Pumpkin –> 423a2ace9b1e747146305116649368dd
As edf8377563f7fa2897df6aa434ad305e is not equal to 423a2ace9b1e747146305116649368dd you won’t be let in. And the server will have no idea what your password was and how close the password you typed was to your real one.
So even if an insider gets a hold of your password hash, they have no easy way of knowing what the original password was. Note however that I am using the phrase “no easy way of knowing” loosely because there are a number of ways to determine your original password and how easy or difficult (or possible) would that be depends on how “strong” the password you chose was. As a side note, most authentication servers salt these passwords with random keys before hashing them, so it is even harder to attack them without knowing the salt.
I’ll talk about how hashes can be are attacked and how to protect yourself against them by choosing strong passwords another time.
The second step to solve the Rubik’s Cube is to complete the second (center) row.
After you complete Step 1 , you will end up having 4 edge pieces on each side that require replacement. The correct edge pieces are often at the bottom of the cube, or sometimes on the sides of the cube but in the wrong locations.
The sequence you need to learn to complete Step 2 is one of the easiest. You basically do three things:
- At the bottom (green) side find the two faced edge pieces you can use (combination of red, yellow, white and orange)
- Align them to the correct position
- Follow the sequence to replace the edge with the correct piece
Now look at the cube below after we’ve finished the first step. The top is all done. The edges that are marked by white rectangles are what we are going to fix. Note that there is another one at the back that is invisible.
 Starting the second step
We now turn the cube upside down, so the green side is on top. We only care about the edge pieces at this point. To be more precise, we care about the edge pieces that do not have green on them, because the green pieces will end up at the bottom. The two white squares on the figure below show the red-white location and its matching piece at the top left. The red squares show the red-yellow location and its matching edge on the top right. As so it happens, the yellow-red piece is already at the right spot so I simply rotate the left column (the location where it should go) up to align the location and the piece.
 Analyzing the bottom
After I moved the left column up, note that the piece and the location is facing each other. The only thing you have to be careful at this stage is to make sure that the red-yellow piece is oriented correctly, otherwise you can place the edge into the right location but with inverted colors. Try to visualize the edge piece rotating towards the location. After the move the red will face up and yellow will face the opposite side. In the picture below note the red boxes. The right box is the edge and it will rotate towards the box on the left as indicated by the white arrow.
 Aligning the location with the edge
Once you’ve aligned the location and the edge piece, you turn the cube upside down again to find out that one column of the blue size is now pulled down facing you. Note that the red arrows show your next move.
 Starting the sequence
Then you simply apply the rules of the sequence:
1) Turn the bottom row to the same direction as the side column was rolled down. So if the left column was rolled down turn the row to the left (clockwise), if the right side column was rolled down turn the bottom row to the right (counter clockwise). In this case it is the right column, so we rotate the bottom row to the right (counter clockwise)
 Move 1
2) Turn the side column back to where it was before. This will effectively change the orientation of your corner piece.
 Move 2
3) Turn the bottom row one more time to the same direction as in Move 1 to get it out of the way.
 Move 3
4) Now roll the column down from the perpendicular side.
 Move 4
5) Put the corner piece into place by rotating the bottom row to the opposite direction of Moves 1 and 3 (left)
 Move 5
6) Fix the side column by rolling it back up.
 Move 6
And there you go. The red and yellow edge piece is now in the right location and the rest of the cube is still intact.
You essentially repeat the same sequence for all the four edges. Here is a fast forward version for the orange-white edge. The red and orange faces are hard to distinguish in the pictures, so I marked critical moves with white squares. In the first picture I locate the correct piece and the location it should go in. I rotate the top 180 degrees in the second move. I move the location towards the piece to align them in the third move. Picture 4 is again move 3 but from another point of view (top). After this point I just apply the sequence till the orange-white piece is in place.
 Step 2
If you make a mistake you don’t have to go all the way back. For instance if you adjust the orientation wrong and end up with an orange-white piece where you needed a white-orange piece, simply apply the sequence to replace the piece there, and then try again. Sometimes this happens randomly without you making a mistake, in which case this is the only way to fix it anyways. Here is another optimization tip: Don’t worry about the edges that are in the wrong places and always start with the ones available at the bottom of the cube. When you place them they will most probably take the others out to where you need them.
I first got introduced to the Rubik’s Cube when I was about 10 years old. That was early 80′s and it was almost as hip as heavy metal music and mullets; so you had to try hard not to bump into one. I happened to be a boarding student at the time, and all of my classmates were frantically trying to solve it. I don’t remember who learned it from whom first, but after a while we were in a fierce competition to break the best time record.
When I was at a business meeting in Boston couple of months ago I was browsing a toy store to buy a little present for my 5 year old son. When I saw the Rubik’s Cube I bought it without thinking twice. After struggling a while to remember, I was surprised that I could remember all the steps to solve it in a couple of hours (it takes only couple of minutes once you get the hang of it).
I like the Rubik’s Cube. It provides a physical analogue to some cryptography concepts, and it is also a very neat demonstration of the use of subroutines in software development. It teaches you how to divide a big problem into smaller problems and solve one by one to reach the ultimate goal. But most of all it is fun. So if you want to learn how to do it just read on.
I kept the introduction long because there actually are no magic tricks to do the first step. So you have to figure out this step all by yourself. It is pretty straight-forward though, so no need to panic.
A solved (or unscrambled) cube looks like this:
 Rubik's Cube
Traditionally we hold it so that the blue face is at the top, green is at the bottom and the other colors are on the sides. You don’t have to hold it like this, but to make my life easier when I am describing the steps I’ll follow this convention. Once you learn how to solve it you can go with any color you like. The magical thing about the cube is that you can rotate any row left or right, and you can rotate any column up or down. When you rotate any row or column 90, 180 or 270 degrees, the little cube segments form a perfect cube again, but with a totally different color configuration. If you play with it a little bit, you’ll see that moving the colors where you want to take them is not as easy as it looks without spoiling what you have already done. The steps of solution actually are nothing more than “algorithms” or “sequences” of moves that will move a specific cube piece to another location while keeping rest the cube intact.
 Names and definitions
Before going any further, let’s clarify some terms and definitions. The center pieces are in the middle of each face and they never rotate with respect to each other. Center pieces have only one color on them. Edges are in the middle of each side and have two colors. Corners are at the intersection of three different faces and have three colors. We can turn edges and corners up, down, left or right. Note that the entire row or column will turn around the center of the cube.
 Step 1: Solving the top
In the picture above I showed an example of how to complete Step 1, which is done when you have collected all the blue faces on top AND also made sure that the first row colors on the sides are in sync with each other. Note that I didn’t show all the steps. To simplify the problem you can just get the blue face in place first and then fix the side colors later. I personally align the center squares with the matching edge pieces (e.g. blue and white, blue and red, etc) first then locate the correct corner colors and bring them up to the right place one by one.
If you have trouble finishing this part here are a couple of pointers:
To replace a corner piece
- Bring the correct corner piece just to the south of the side column where it should eventually go. Note if your side column is on the right or left.
- Make sure the blue piece is facing you, other two colors are aligned correctly.
- Now turn the correct piece to the opposite direction of the side. For instance, if it is a left corner piece turn it to the right, if it is a right corner piece turn it to the left.
- Roll the side column down.
- Bring the corner piece where it was before. This should effectively put it into place.
- Roll the side column up again.
To replace an edge piece
- Bring the correct piece just to the south of where it should eventually go.
- Make sure the blue piece is facing you.
- Now move the bottom row left or right (doesn’t matter)
- Roll the center row down.
- Turn the bottom row where it was before (left or right).
- Roll the center row up.
Next time I’ll explain the Step 2 sequence.
Cryptography is a word derived from two ancient Greek words, kryptos and graphein which mean hidden and write, respectively. Although the direct translation means something like “hidden write/text”, it is actually the meaning of the text that is hidden, not the text itself.
Hiding the medium on which the message was written is named as “steganography”, again derived from the two Greek words “steganos” and “graphein”, which means “covered write/text”. Steganography is based on the premise that the writer of the message outsmarts possible intruders by hiding the message by some means. The most classical example of this is the invisible ink, where the message is writen with some liquid (urine or lemon juice is common) that is invisible to the naked eye, but can be revealed by some sort of mechanism, such as showing it to fire, looking at it in dark under the UV light, etc.
In the cold war era, microdots were popular to transmit micro films as a “dot” on a seemingly ordinary letter. My personal favorite is to tatoo the message on the shaved head of a messenger, let his hair grow and send him off to the recipient.
In the modern world, information privacy is almost always provided by cryptography and not by steganography. Some people still choose to hide their keys under the doormat, but this is often the first place an intruder will try to find it. That’s why we lock things up if they are important to us. Locking things up doesn’t hide valuable things, but it makes them harder to get to. It is wise to do both, that is, lock them to an out-of-sight location.
So what is cryptography? How do we exactly hide the content of a message without hiding the mesage itself? The simplest example is the Caesar Shift Cipher, which dates back to 200 AD, and possibly is still the number one choice for kids to send secret messages today.
It is very simple. You basically write down the alphabet and shift every letter by a number of letters up or down. Assume we chose to shift 3 letters up, then the base alphabet and the shifted alphabet together will look like this:
abcdefghijklmnopqrstuvwxyz
defghijklmnopqrstuvwxyzabc
So now a corresponds to d, b corresponds to e, and so forth.
If you are familiar with my other blogs about music theory, you’ve already noticed that using the cipher shift is no different then transposing music from one key to another. Going back to cryptography, If I want to encrypt the secret message “This is a secret message”, I write it as:
“Wkfv lv d vhfuhw phvvdjh”
Caesar Shift Cipher is far too simple to have any practical value today, yet it still demonstrates all components of an encryption/decryption schema. Therefore I’ll explain some basic terms using the Caesar Cipher Shift.
- The original message prior to encryption is called the “plain text” or the “clear text” message.
- The garbled message after encryption is called the “cipher text” or sometimes the “encrypted text“.
- The algorithm is the “Caesar Cipher Shift“, which has a mathematical rule that can be repeated by anyone who knows what that is (i.e. shift 3 letters up)
- The key is 3, which is basically the parameter of the algorithm that determines how many letters should we shift.
This type of encryption is called a “symmetric encryption“, because the same key is used both to encrypt an decrypt the message. This symmetry is very obvious in the following diagram which shows the full life cycle of the entire crypto operation.
 Symmetric Encryption
In modern cryptography we stick to the Kerckhoffs’ Principle, which suggests that the security of a crypto-system must not depend on keeping the crypto-algorithm secret. The security should depend only on keeping the key secret. On November 23, 1976 Feistel’s (IBM) Lucifer cipher was officially adopted as America’s official standard for encryption (called DES, Data Encryption Standard thereafter). DES was only recently replaced by AES (Advanced Encryption Standard) on September 2000 (Rijndael algorithm).
Despite standardization and strength of AES, the key distribution problem prevented cryptography become mainstream.
Symmetric encryption is very secure, provided that the sender and the receiver both know (or have) the same key. In cases where sharing the key is not practical, such as for two people who do not know each other or when multiple parties are involved, this poses a big issue. Good thing there are solutions for these and I’ll talk about them later.
|
|