According to the US government, a valid social security number comes in three groups - a group of 3 numbers, then a group of 2 numbers, then a group of 4 numbers. The first 3 numbers are assigned to individual states, territories, or groups of people. They start with 001, and currently go up to 772. (Although, technically, a lot of those upper numbers haven't been used yet. But since they have been assigned, it is possible they could be used soon). The second group of numbers is 01 through 99. (There's a formula for how they are assigned, starting with the odd numbers 02 through 08, then the even numbers 11 through 99, or something similar to that. But every number 01 through 99 could be possible). The last group of numbers is 0001 through 9999 and are assigned sequentially.

So, the regular expression should check for all these things. Normally, people will type in a regular expression with a space or a dash between the groups of numbers, or no punctuation. The regular expression allows for all those scenarios. And to make things easier, the check for no "0" in a group ("000" in the first group, "00" in the second group, or "0000" in the third group) is pulled out into separate checkd at the end.

Here is the JavaScript validation function:

function isValidSSN(value) {

var re = /^([0-6]\d{2}|7[0-6]\d|77[0-2])([ \-]?)(\d{2})\2(\d{4})$/;

if (!re.test(value)) { return false; }

var temp = value;

if (value.indexOf("-") != -1) { temp = (value.split("-")).join(""); }

if (value.indexOf(" ") != -1) { temp = (value.split(" ")).join(""); }

if (temp.substring(0, 3) == "000") { return false; }

if (temp.substring(3, 5) == "00") { return false; }

if (temp.substring(5, 9) == "0000") { return false; }

return true;

}

The first thing we do is test the reasonableness with a regular expression. Let me describe what the regular expression is doing.

^([0-6]\d{2}|7[0-6]\d|77[0-2])

In the first group, the valid numbers are 001 through 772. The "^" at the front says the value must start with this - there can't be anything before it in the value. 000 will be handled later. So this part of the regular expression checks for the values 000 through 772. Note that there are three groups of checks that are "or"ed together using the | character. If the numbers 0 through 6 appear in the first position (that's what "[0-6]" says - the group of characters in ASCII order between "0" and "6", inclusive), then any two numbers (\d means "digit" and {2} means "exactly two") can follow it. If the number 7 is followed by any number 0 through 6, then the last number can be any digit ("{1}" isn't needed, but could be used). If the first two numbers are 77, then the last number must be in the range 0 through 2. So that's what the first part of the regular expression is doing.

([ \-]?)

This checks for the separator. The value can be either a space or a dash, and must occur zero or one time (zero allows for no punctuation). The "?" character means "the preceeding must occur a maximum of one time, but it doesn't have to appear". The parentheses around the grouping will "remember" the value. But there's parentheses around the first part as well, so this is the second group that is remembered.

(\d{2})\2

This is the check for the second group of numbers. Since "00" will be handled later, we can check for any two digits. After that, we repeat the check for the second remembered group in the regular expression. So, if a dash was used to separate the first and second groups, a dash must be used here. That's what the "\2" does - it says "repeat the second remembered expression". If it was "\3" it would repeat the third remembered expression. But also keep in mind that "\2" isn't the same as "[ -]?" -- if I used the latter, a value of "123-45 6789" would pass. Using the "repeat" syntax assures that the exact same group used to pass the previous test must be used to pass this test as well.

(\d{4})$

Finally, the last group must be four digits (we'll check for "0000" later on) and this must terminate the string (that's what the "$" character does). So the entire regular expression checks for strings like "123-45-6789". "773-45-6789" will fail ("772" in the first group is the largest value allowed). But "000-00-0000" will pass when we don't want it to.

So the next thing we do is build a temporary variable with no punctuation. It will be a string of 9 digits. If a dash is used as a separator, then the original string is split up into an array of 3 parts (based on the dash) and then joined back into a string based on an empty string. So we end up with a string of 9 character digits.

Once we have the 9 characters, we can check to see if the first three are "000", the last four are "0000", and the middle two are "00". If any of those checks result in a match, then the number isn't valid. If we get past those three checks, then the social security number is a reasonable number and we return the value true.

You can test out the code using the field below: