<?
//
// [ssn_verify] v1.0
// Copyright(c) 2004 Josh L. Reznick
// email: jrez(at)jrez.com
//
// [ssn_verify] determines whether or not a particular Social Security Number
// has been issued by the Social Security Administration based on their
// (bizzare) sequence of number issuance. It also checks for known bogus
// numbers, such as ones that havebeen used in advertising. Please see below
// for information on how to update the SSN issuance data based on the SSA's
// Monthly Issuance Table.
//
// [ssn_verify] is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// [ssn_verify] is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// If you do find this script useful, please drop me an email. I am very
// interested to know the various uses people have for this functionality.
// Thanks!
//
// -------------------------------------------------------------------------
//
// The data below is taken from the November 2004 SSA Monthly Issuance Table.
// You can update the data at any time by simply cutting and pasting the data
// found at http://www.ssa.gov/employer/highgroup.txt into the variable below.
//
// NOTE: Chances are you will only be using this function to validate adult
// SSN's- If that is the case, then you have a good 18 years before there are
// any adults with SSNs that are not included in the data below.
//
$ssn_data = "
001 02 002 02 003 98 004 06 005 06* 006 04
007 04 008 88 009 86 010 88 011 88 012 88
013 88 014 88 015 88 016 88 017 88 018 88
019 88 020 88* 021 86 022 86 023 86 024 86
025 86 026 86 027 86 028 86 029 86 030 86
031 86 032 86 033 86 034 86 035 70 036 70
037 70 038 70 039 68 040 08 041 08* 042 06
043 06 044 06 045 06 046 06 047 06 048 06
049 06 050 94 051 94 052 94 053 94 054 94
055 94 056 94 057 94 058 94 059 94 060 94
061 94 062 94 063 94 064 94 065 94 066 94
067 94 068 94 069 94 070 94 071 94 072 94
073 94 074 94 075 94 076 94 077 94 078 94
079 94 080 94* 081 94* 082 94* 083 94* 084 92
085 92 086 92 087 92 088 92 089 92 090 92
091 92 092 92 093 92 094 92 095 92 096 92
097 92 098 92 099 92 100 92 101 92 102 92
103 92 104 92 105 92 106 92 107 92 108 92
109 92 110 92 111 92 112 92 113 92 114 92
115 92 116 92 117 92 118 92 119 92 120 92
121 92 122 92 123 92 124 92 125 92 126 92
127 92 128 92 129 92 130 92 131 92 132 92
133 92 134 92 135 15 136 15 137 15 138 15
139 15 140 15* 141 13 142 13 143 13 144 13
145 13 146 13 147 13 148 13 149 13 150 13
151 13 152 13 153 13 154 13 155 13 156 13
157 13 158 13 159 82 160 82 161 82 162 82
163 82 164 82 165 82 166 82 167 82 168 82
169 82 170 82 171 82 172 82 173 82 174 82
175 82 176 82 177 82 178 82 179 82 180 82*
181 80 182 80 183 80 184 80 185 80 186 80
187 80 188 80 189 80 190 80 191 80 192 80
193 80 194 80 195 80 196 80 197 80 198 80
199 80 200 80 201 80 202 80 203 80 204 80
205 80 206 80 207 80 208 80 209 80 210 80
211 80 212 71 213 71 214 71* 215 69 216 69
217 69 218 69 219 69 220 69 221 98 222 98
223 99 224 99 225 99 226 99 227 99 228 99
229 99 230 99 231 99* 232 51 233 51 234 51
235 49 236 49 237 99 238 99 239 99 240 99
241 99 242 99 243 99 244 99 245 99 246 99
247 99 248 99 249 99 250 99 251 99 252 99
253 99 254 99 255 99 256 99 257 99 258 99
259 99 260 99 261 99 262 99 263 99 264 99
265 99 266 99 267 99 268 11 269 11 270 11*
271 11* 272 08 273 08 274 08 275 08 276 08
277 08 278 08 279 08 280 08 281 08 282 08
283 08 284 08 285 08 286 08 287 08 288 08
289 08 290 08 291 08 292 08 293 08 294 08
295 08 296 08 297 08 298 08 299 08 300 08
301 08 302 08 303 29 304 29 305 27 306 27
307 27 308 27 309 27 310 27 311 27 312 27
313 27 314 27 315 27 316 27 317 27 318 04
319 04 320 04 321 04 322 04 323 04 324 04
325 04 326 04 327 04* 328 04* 329 04* 330 02
331 02 332 02 333 02 334 02 335 02 336 02
337 02 338 02 339 02 340 02 341 02 342 02
343 02 344 02 345 02 346 02 347 02 348 02
349 02 350 02 351 02 352 02 353 02 354 02
355 02 356 02 357 02 358 02 359 02 360 02
361 02 362 31 363 31 364 31 365 31 366 31
367 31 368 31 369 31 370 31* 371 29 372 29
373 29 374 29 375 29 376 29 377 29 378 29
379 29 380 29 381 29 382 29 383 29 384 29
385 29 386 29 387 25 388 25 389 25 390 25
391 25 392 25 393 25 394 25 395 25* 396 23
397 23 398 23 399 23 400 63 401 63 402 63
403 63* 404 61 405 61 406 61 407 61 408 99
409 97 410 97 411 97 412 97 413 97 414 97
415 97 416 57 417 57 418 57 419 57 420 57
421 57 422 57 423 57* 424 55 425 95 426 95
427 95 428 95 429 99 430 99 431 99 432 99
433 99 434 99 435 99 436 99 437 99 438 99
439 99 440 19 441 19 442 19 443 19 444 19
445 19 446 19 447 19* 448 17 449 99 450 99
451 99 452 99 453 99 454 99 455 99 456 99
457 99 458 99 459 99 460 99 461 99 462 99
463 99 464 99 465 99 466 99 467 99 468 45
469 45 470 45 471 45 472 45 473 45 474 43
475 43 476 43 477 43 478 35 479 35 480 33
481 33 482 33 483 33 484 33 485 33 486 21
487 21 488 21 489 21 490 21 491 21 492 21
493 21 494 21 495 21 496 21 497 21 498 21
499 21 500 19 501 31 502 29 503 37 504 35
505 47 506 47 507 47 508 47 509 23 510 23
511 23 512 23 513 23 514 23 515 23 516 41
517 39 518 69 519 69 520 49 521 99 522 99
523 99 524 99 525 99 526 99 527 99 528 99
529 99 530 99 531 55 532 55 533 55 534 55
535 55 536 53 537 53 538 53 539 53 540 67
541 67 542 67 543 67 544 65 545 99 546 99
547 99 548 99 549 99 550 99 551 99 552 99
553 99 554 99 555 99 556 99 557 99 558 99
559 99 560 99 561 99 562 99 563 99 564 99
565 99 566 99 567 99 568 99 569 99 570 99
571 99 572 99 573 99 574 41 575 99 576 99
577 39 578 37 579 37 580 35 581 99 582 99
583 99 584 99 585 99 586 55 587 95 589 99
590 99 591 99 592 99 593 99 594 99 595 99
596 76 597 76 598 76 599 76* 600 99 601 99
602 47 603 47 604 47 605 47 606 47 607 47
608 47 609 47 610 47 611 47 612 47 613 47
614 47 615 47* 616 47* 617 47* 618 47* 619 47*
620 47* 621 45 622 45 623 45 624 45 625 45
626 45 627 94* 628 94* 629 94* 630 94* 631 92
632 92 633 92 634 92 635 92 636 92 637 92
638 92 639 92 640 92 641 92 642 92 643 92
644 92 645 92 646 78 647 78* 648 36* 649 34
650 34* 651 32 652 32 653 32 654 18 655 18
656 18 657 18 658 18* 659 10 660 10* 661 09
662 09 663 09 664 09 665 09 667 24 668 24
669 24 670 24* 671 22 672 22 673 22 674 22
675 22 676 09* 677 07 678 07 679 07 680 62*
681 05 682 05 683 05 684 05 685 05 686 05
687 05 688 05 689 05* 690 03 700 18 701 18
702 18 703 18 704 18 705 18 706 18 707 18
708 18 709 18 710 18 711 18 712 18 713 18
714 18 715 18 716 18 717 18 718 18 719 18
720 18 721 18 722 18 723 18 724 28 725 18
726 18 727 10 728 14 729 03 730 03 731 03
732 03* 733 01 750 01 764 46* 765 46* 766 34
767 34* 768 34* 769 34* 770 32 771 32 772 32
";
$known_bogus = array(111111111, 222222222, 333333333, 444444444, 555555555,
666666666, 777777777, 888888888, 999999999, 000000000,
123456789, 987654321, 121212121, 101010101, 010101010,
002281852, 042103580, 062360749, 078051120, 095073645,
128036045, 135016629, 141186941, 165167999, 165187999,
165207999, 165227999, 165247999, 189092294, 212097694,
212099999, 306302348, 308125070, 468288779, 549241889);
function getLevelSSN($num) {
if ( ($num<10) && (($num%2)==1) ) $level=1;
if ( ($num>09) && (($num%2)==0) ) $level=2;
if ( ($num<10) && (($num%2)==0) ) $level=3;
if ( ($num>09) && (($num%2)==1) ) $level=4;
return $level;
}
function isValidSSN($ssn) {
global $ssn_data,$known_bogus;
$ssn = str_replace("-","",$ssn);
$area = intval(substr($ssn,0,3));
$group = intval(substr($ssn,3,2));
$serial = intval(substr($ssn,5,4));
preg_match_all("/(\d{3} \d{2})/", $ssn_data, $results, PREG_SET_ORDER);
for($i=0;$i<sizeof($results);$i++) {
list($area_temp,$group_temp) = explode(" ",$results[$i][1]);
$group_val[$area_temp] = $group_temp;
}
$high = $group_val[$area];
$group_level = getLevelSSN($group);
$high_level = getLevelSSN($high);
if ($group_level<$high_level) $pass=true;
if ( ($group_level==$high_level) && ($group<=$high) ) $pass=true;
if ( ($area==0) || ($group==0) || ($serial==0) ) $pass=false;
if ( ($area==666) || ( ($area>699) && ($area<729) ) || ($area>899) ) $pass=false;
if ( (strlen($ssn)!=9) || (!is_numeric($ssn)) ) $pass=false;
for($i=0;$i<sizeof($known_bogus);$i++) if (intval($ssn)==$known_bogus[$i]) $pass=false;
return $pass;
}
?>