信用卡号码的解析(转)

作者 Michael Gilleland, Merriam Park Software
翻译: 王建平

介绍
这不是一篇关于信用卡本身的文章<wbr>。如果你正寻找这样的文章推荐您去参考一下Joe Ziegler的Everyth<wbr>ing You Ever Wanted to Know about Credit Cards系列名著。本文的范围<wbr>仅仅限定在信用卡的号码解析上,<wbr>同时提供了一个能够验证信用卡号<wbr>码有效性的java源码。<br>信用卡的编号方式规范已经由International<wbr> Standards Organization (ISO/IEC 7812-1:1993)和Am<wbr>erican National Standards Institute (ANSI X4.13)规定。这两个著名的<wbr>机构拒绝将他们的出版物免费放到<wbr>互联网上来,所以接下来本文关于<wbr>信用卡号码格式的消息大量来自于<wbr>Internet Engineering Task Force (IETF) Donald E. Eastlake 3rd的"ISO 7812/7816 Numbers and the Domain Name System (DNS)"草案 (draft-eastlake<wbr>-card-map-08, expires August 2001),http://ww<wbr>w.globecom.net/<wbr>ietf/draft/draf<wbr>t-eastlake-card<wbr>-map- 08.html。我没有将链接加<wbr>上,因为个人版的IETF草案生<wbr>命都很短。<br>本文的数字编号是从左到右的,"<wbr>第一个"数字表示最左的数字。 <br><strong><font style="FONT-SIZE: 12pt" size="5">主行业标识符</font></strong><br>信用卡的前6个数字组成发行者标<wbr>识符(包含主行业标识符)。也就<wbr>是说可能的发行者将有10000<wbr>000个 (10的6次方)。 <br>下面列出了一些知名发行者的标识<wbr>符:<br>发行者 标识符 卡号长度<br>Diner's Club/Carte Blanche 300xxx-305xxx,<br> 36xxxx, 38xxxx 14<br>American Express 34xxxx, 37xxxx 15<br>VISA 4xxxxx 13, 16<br>MasterCard51xxxx-55xxxx 16<br>Discover 6011xx 16<br>ISO 3166规定发行者标识符中,如<wbr>果MII数字是9,后面的3个数<wbr>字是3位数字的国家代码,剩下的<wbr>两位数字可以由所属国家自行定义<wbr>。 <br><strong><font style="FONT-SIZE: 12pt" size="5">帐号Account</font></strong><br>信用卡的第7到(n - 1)数字为你个人的帐号标识符。<wbr>信用卡的数字最长为19位。卡的<wbr>前6为数字为发行者标识符,最后<wbr>一位为校验位,所以卡号的长度可<wbr>以是7到19位。每一个发行者有<wbr>1万亿个可能的帐号(10的12<wbr>次方)。<br>在有大量用户,发行者采取高利率的<wbr>话可以想象信用卡行业将是一个能<wbr>产生大量钱的行业。大多数文明时<wbr>代都认为高利贷是违反自然规则和<wbr>不可饶恕的,不符合商业惯例。 (Aristotle, Politics 1.10; St. Thomas Aquinas, De Malo 13.4; Dante, Inferno 11.94-111; etc.). <br></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

校验位CVV
你信用卡号的最后一位数字为校验<wbr>位。计算正确校验位的算法称作Luhn算法。这个<wbr>算法是以IBM科学家Hans Peter Luhn (1896-1964)的名字命<wbr>名的,Luhn曾经在1960年<wbr>获得美国2950048号专利 ("校验数字的计算者")。Lu<wbr>hn的简历详情可以参考, <br>美国信息科学与技术界网站上的生<wbr>平<a href="http://www.asis.org/Features/Pioneers/luhn.htm"><font color="#ffffff"><u>http://www.asis<wbr>.org/Features/P<wbr>ioneers/luhn.ht<wbr>m</wbr></wbr></wbr></u></font></a>. <br>Susan K. Soy编写的Notes,"H.<wbr>P. Luhn and Automatic Indexing" <a href="http://www.gslis.utexas.edu/%7Essoy/organizing/l391d2c.htm"><font color="#ffffff"><u>http://www.gsli<wbr>s.utexas.edu/~s<wbr>soy/organizing/<wbr>l391d2c.htm</wbr></wbr></wbr></u></font></a> <br>感谢Aleksandar Janicijevic给我提供<wbr>关于H.P. Luhn的信息。 <br>我从黑客杂志phrack 47-8上找到了关于Luhn算<wbr>法最好的描述:"对于偶数个数字<wbr>的卡号。将所有第奇数个数字乘以<wbr>2,如果大于9就减去9。将所有<wbr>得到的偶数于原先的偶数全部相加其结果必须是10的倍数,<wbr>否则卡号无效。如果卡号有奇数个<wbr>数字,则应将第偶数个数字乘以2<wbr>,其余步骤相同。" <br>奇偶这一点有点乱。关键在于我们<wbr>不想将校验位翻倍,我们从校验位<wbr>开始倒着将每一位相加这样做很容<wbr>易。详细情况可以看下面的源码。<wbr><br><font size="5"><strong style="FONT-SIZE: 12pt">例子</strong></font><br>这个例子是取自我2001年八月<wbr>份收到的邮件宣传品。邮件宣传品<wbr>一般会包含大量的信用卡图片。示<wbr>例号码就从中取了一个。 <br><strong><font style="FONT-SIZE: 12pt" size="4">4408 0412 3456 7890</font></strong><br>第一个信用卡提供者展示的卡图片<wbr>上的号码为4408 0412 3456 7890. <br>MII是4 (银行和金融业),发行者标识符<wbr>为440804 (VISA卡的合作伙伴),账户<wbr>号码为123456789,校验<wbr>位为0<br>我们用Luhn算法检查一下44<wbr>08 0412 3456 7890。可以得到下列表格,<br>第一行为原号码<br>第二行,交替将数字乘以2。注意<wbr>不要将校验位乘以2。<br>第三行将所有的结果限制到10以<wbr>下,如果必要话要减去9。<br>最后一行是将要加起来的所有结果<wbr>数字。<br>4 4 0 8 0 4 123 4 5 6 7 8 9 0<br>4x2=8 4 0x2=0 8 0x2=0 4 1x2=2 2 3x2=6 4 5x2=10 6 7x2=14 8 9x2=18 0<br> 8 4 0 8 0 4 2 2 6 410-9=1614-9=58 18-9=9 0<br> 8 4 08 0 4 2 26 4 1 6 5 8 9 0<br>将最后一行的数字加起来得到的结<wbr>果为67,不是10的倍数,那么<wbr>我们得到的结论是4408 0412 3456 7890不是一个有效的信用卡号<wbr>码。<br>如果将校验位由0变成3则号码变<wbr>为4408 0412 3456 7893,这个号码可以通过Lu<wbr>hn算法的检验,因为所有数字相<wbr>加的结果为70可以10整除。所<wbr>以表面上来看4408 0412 3456 7893是一个合法的卡号。 <br></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

4417 1234 5678 9112
第二个信用卡提供者展示的卡图片<wbr>上的号码为4417 1234 5678 9112. <br>MII是4 (银行和金融业),发行者标识符<wbr>为441712 (VISA合作伙伴),帐号为3<wbr>45678911,校验位是2.<wbr><br>我们来应用一下Luhn算法检验<wbr>4417 1234 5678 9112,跟上一个例子一样。<br> 4 417 12 34 56 7 8 9 11 2<br>4x2=8 4 1x2=2 7 1x2=2 2 3x2=6 4 5x2=10 6 7x2=14 8 9x2=18 1 1x2=2 2<br> 8 4 2 7 2 2 6 4 10-9=1 614-9=5 8 18-9=9 1 2 2<br> 8 4 2 7 2 2 6 4 1 6 58 9 12 2<br>将最后一行的数字相加得到的结果<wbr>为69不是10的倍数,结论是4<wbr>417 1234 5678 9112不是有效的信用卡号码。<wbr><br>如果将校验为由2变成3,卡号变<wbr>为4417 1234 5678 9113, 这个号码可以通过Luhn算法的<wbr>检验,因为所有数字相加的结果为<wbr>70可以10整除。所以表面上来<wbr>看4417 1234 5678 9113是一个合法的卡号。 <br>警告<br>这两个包含信用卡卡号图片的推销<wbr>,其卡号被Luhn算法检验是错<wbr>误的。改变一下他们的校验为表面<wbr>上是正确的。但是如果是我,我不<wbr>会购买任何一个这样的东西。 </wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

Java源码
下面的java类可以随意使用,<wbr>不受任何限制。 </wbr>

  1. //---------------------------------------------------------
  2. //ChecksforvalidcreditcardnumberusingLuhnalgorithm
  3. //---------------------------------------------------------
  4. publicabstractclassLuhnCheck{
  5. //--------------------------------
  6. //Filteroutnon-digitcharacters
  7. //--------------------------------
  8. privatestaticStringgetDigitsOnly(Strings){
  9. StringBufferdigitsOnly=newStringBuffer();
  10. charc;
  11. for(inti=0;i<s.length();i++){
  12. c=s.charAt(i);
  13. if(Character.isDigit(c)){
  14. digitsOnly.append(c);
  15. }
  16. }
  17. returndigitsOnly.toString();
  18. }
  19. //-------------------
  20. //PerformLuhncheck
  21. //-------------------
  22. publicstaticbooleanisValid(StringcardNumber){
  23. StringdigitsOnly=getDigitsOnly(cardNumber);
  24. intsum=0;
  25. intdigit=0;
  26. intaddend=0;
  27. booleantimesTwo=false;
  28. for(inti=digitsOnly.length()-1;i>=0;i--){
  29. digit=Integer.parseInt(digitsOnly.substring(i,i+1));
  30. if(timesTwo){
  31. addend=digit*2;
  32. if(addend>9){
  33. addend-=9;
  34. }
  35. }
  36. else{
  37. addend=digit;
  38. }
  39. sum+=addend;
  40. timesTwo=!timesTwo;
  41. }
  42. intmodulus=sum%10;
  43. returnmodulus==0;
  44. }
  45. //-----
  46. //Test
  47. //-----
  48. publicstaticvoidmain(String[]args){
  49. StringcardNumber="4408041234567890";
  50. booleanvalid=LuhnCheck.isValid(cardNumber);
  51. System.out.println(cardNumber+":"+valid);
  52. cardNumber="4408041234567893";
  53. valid=LuhnCheck.isValid(cardNumber);
  54. System.out.println(cardNumber+":"+valid);
  55. cardNumber="4417123456789112";
  56. valid=LuhnCheck.isValid(cardNumber);
  57. System.out.println(cardNumber+":"+valid);
  58. cardNumber="4417123456789113";
  59. valid=LuhnCheck.isValid(cardNumber);
  60. System.out.println(cardNumber+":"+valid);
  61. }
  62. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值