# C validating a credit card number

The length is in between 13 to 19 characters and contains only **numbers** and no space in between.

*Credit* *Card* / Debit *Card* *Number* Checker tool is designed to check the validity of *Credit* *Card* / Debit *Card* *Number* and check the (BIN) base on updated database.

Finally, you add both totals together and if the result is evenly divisible by 10, then the *card* has passed validation.

Of course, this would be clearer with a bit of code and Listing 1 shows my method assumes that all spaces and other non-digit characters have been stripped from the **card** **number** string.

The tool support all major **Credit** **Card** & Debit **Cards** brands such as as VISA, Master **Card**, American Express, Diner's Club, JCB & Voyager.

Currently, there are more than 300,000 unique BIN in our database.

What the authors of those tutorials and sample code forget is that many people who are searching for pre-existing code and tutorials are doing so because they are not experienced enough in their programming language of choice to be able to implement the API on their own.

Without a valid owner name, an expiration date and a valid CVV code, they can't be used for real transactions.

To validate, type the **Credit** **Card** or Debit **Card** **Number** in the specified field below.

Make sure that the **Credit** **Card** or Debit **Card** **Number** follows the proper format.

Those companies using *credit* *card* *numbers* that can be validated by the Luhn test have *numbers* that pass the following test: Reverse the digits: 61789372994 Sum the odd digits: 6 7 9 7 9 4 = 42 = s1 The even digits: 1, 8, 3, 2, 9 Two times each even digit: 2, 16, 6, 4, 18 Sum the digits of each multiplication: 2, 7, 6, 4, 9 Sum the last: 2 7 6 4 9 = 28 = s2 s1 s2 = 70 which ends in zero which means that 49927398716 passes the Luhn test* Luhn test of *credit* *card* *numbers* 22/05/2016LUHNTEST CSECT USING LUHNTEST, R13 base register B 72(R15) skip savearea DC 17F'0' savearea STM R14, R12,12(R13) prolog ST R13,4(R15) " ST R15,8(R13) " LR R13, R15 " LA R9, T @t(k) LA R8, N for n LOOPK EQU * for k=1 to n LR R4, R9 @t(k),@s[1] LA R6,1 from i=1 LA R7, M to m LOOPI1 CR R6, R7 for i=1 to m BH ELOOPI1 leave i CLI 0(R4), C' ' if mid(s,i,1)=" " BNE ITERI1 then BCTR R6,0 i-1 ST R6, L l=i-1 B ELOOPI1 exit for* end if ITERI1 LA R4,1(R4) next @s[i] LA R6,1(R6) i=i 1 B LOOPI1 next i ELOOPI1 EQU * out of loop i MVC W, BLANK w=" " LA R4, W [email protected] LR R5, R9 [email protected] A R5, L [email protected] l BCTR R5,0 is=s l-1 L R6, L i=l LA R7,1 to 1LOOPI2 CR R6, R7 for i=l to 1 by -1 BL ELOOPI2 leave i MVC 0(1, R4),0(R5) mid(w,iw,1)=mid(s,is,1) LA R4,1(R4) iw=iw 1 BCTR R5,0 is=is-1 BCTR R6,0 i=i-1 B LOOPI2 next i ELOOPI2 EQU * out of loop i LA R11,0 s1=0 LA R12,0 s2=0 LA R6,1 i=1 L R7, L to l LOOPI3 CR R6, R7 for i=1 to l BH ELOOPI3 leave i LA R2, W-1 @w-1 AR R2, R6 w[i] MVC CI,0(R2) ci=mid(w,i,1) NI CI, X'0F' zap upper half byte LR R4, R6 i SRDA R4,32 0 BNH NOTMOD then XR R2, R2 clear IC R2, CI z=cint(mid(w,i,1)) AR R11, R2 s1=s1 cint(mid(w,i,1)) B EIFMOD else NOTMOD XR R2, R2 clear IC R2, CI cint(mid(w,i,1)) SLA R2,1 *2 ST R2, Z z=cint(mid(w,i,1))*2 C R2,=F'10' if z% returns true if cc *Number* passes the Luhn test, false otherwise %% as Algol W has fixed length strings, the length of the *number* %% must be specified in cc Length %logical procedure Luhn Test ( string(32) value cc *Number* ; integer value cc Length ) ;begin integer check Sum; logical odd Digit, is Valid; check Sum := 0; is Valid := odd Digit := true; for c Pos := cc Length step -1 until 1 do begin integer digit; digit := decode( cc *Number*( c Pos - 1 // 1 ) ) - decode( "0" ); if digit 9 then is Valid := false else if odd Digit then check Sum := check Sum digit else check Sum := check Sum ( case digit 1 of ( 0, 2, 4, 6, 8 , 1, 3, 5, 7, 9 ) ); odd Digit := not odd Digit end for_c Pos ; is Valid and ( ( check Sum rem 10 ) = 0 )end Luhn Testbegin % external procedure that returns true if cc *Number* passes the Luhn test, false otherwise % logical procedure Luhn Test ( string(32) value cc *Number* ; integer value cc Length ) ; algol "LUHN" ; % task test cases % procedure test Luhn Test ( string(32) value cc *Number* ; integer value cc Length ) ; write( s_w := 0, cc *Number*, if Luhn Test( cc *Number*, cc Length ) then " is valid" else " is invalid" ); test Luhn Test( "49927398716", 11 ); test Luhn Test( "49927398717", 11 ); test Luhn Test( "1234567812345678", 16 ); test Luhn Test( "1234567812345670", 16 ) end.global _start_start: ldr r0, =example_numbers bl test_number add r1, r0, #1 bl length add r0, r1, r0 bl test_number add r1, r0, #1 bl length add r0, r1, r0 bl test_number add r1, r0, #1 bl length add r0, r1, r0 bl test_number mov r0, #0 mov r7, #1 swi 0 test_number: push bl print_string bl luhn_test cmp r0, #1 ldreq r0, =valid_message ldrne r0, =invalid_message bl print_string pop mov pc, lr print_string: push mov r1, r0 @ string to print bl length mov r2, r0 @ length of string mov r0, #1 @ write to stdout mov r7, #4 @ SYS_WRITE swi 0 @ call system interupt pop mov pc, lr @ r0 address of *credit* *card* *number* [email protected] returns result in r0luhn_test: push mov r1, r0 bl is Numerical @ check if string is a *number* cmp r0, #1 bne .luhn_test_end @ exit if not *number* mov r0, r1 ldr r1, =reversed_string @ address to store reversed string bl reverse @ reverse string push bl length @ get length of string mov r4, r0 @ store string length in r4 pop mov r2, #0 @ string index mov r6, #0 @ sum of odd digits mov r7, #0 @ sum of even digits Next: ldrb r3, [r1, r2] @ load byte into r3 sub r3, #'0' @ convert letter to digit and r5, r2, #1 @ test if index is even or odd cmp r5, #0 beq .odd_digit bne .even_digit .odd_digit: add r6, r3 @ add digit to sum if odd b .continue @ skip next step .even_digit: lsl r3, #1 @ multiply digit by 2 cmp r3, #10 @ sum digits subge r3, #10 @ get digit in 1s place addge r3, #1 @ add 1 for the 10s place add r7, r3 @ add digit sum to the total .continue: add r2, #1 @ increment digit index cmp r2, r4 @ check if at end of string blt Next add r0, r6, r7 @ add even and odd sum mov r3, r0 @ copy sum to r3 ldr r1, =429496730 @ (2^32-1)/10 sub r0, r0, r0, lsr #30 @ divide by 10 umull r2, r0, r1, r0 mov r1, #10 mul r0, r1 @ multiply the r0 by 10 to see if divisible cmp r0, r3 @ compare with the original value in r3 .luhn_test_end: movne r0, #0 @ return false if invalid *card* *number* moveq r0, #1 @ return true if valid *card* *number* pop mov pc, lr length: push mov r2, r0 @ start of string address .loop: ldrb r1, [r2], #1 @ load byte from address r2 and increment cmp r1, #0 @ check for end of string bne @ load next byte if not 0 sub r0, r2, r0 @ subtract end of string address from start sub r0, #1 @ end of line from count pop mov pc, lr @ reverses a [email protected] r0 address of string to [email protected] r1 address to store reversed stringreverse: push push bl length @ get length of string to reverse mov r3, r0 @ backword index pop mov r4, #0 @ fowrard index .reverse_next: sub r3, #1 @ decrement backword index ldrb r5, [r0, r3] @ load byte from original string at index strb r5, [r1, r4] @ copy byte to reversed string add r4, #1 @ increment fowrard index cmp r3, #0 @ check if any characters are left bge .reverse_next mov r5, #0 strb r5, [r1, r4] @ write null byte to terminate reversed string pop mov pc, lr is Numerical: push Numerical_check Next: ldrb r1, [r0], #1 cmp r1, #0 beq Numerical_true cmp r1, #'0' blt Numerical_false cmp r1, #'9' bgt Numerical_false b Numerical_check Next Numerical_false: mov r0, #0 b Numerical_end Numerical_true: mov r0, #1 Numerical_end: pop mov pc, lr .datavalid_message: .asciz " valid *card* *number*\n"invalid_message: .asciz " invalid *card* *number*\n" reversed_string: .space 32 example_numbers: .asciz "49927398716" .asciz "49927398717" .asciz "1234567812345678" .asciz "1234567812345670" FOR *card*% = 1 TO 4 READ cardnumber$ IF FNluhn(cardnumber$) THEN PRINT "*Card* *number* " cardnumber$ " is valid" ELSE PRINT "*Card* *number* " cardnumber$ " is invalid" ENDIF NEXT *card*% END DATA 49927398716, 49927398717, 1234567812345678, 1234567812345670 DEF FNluhn(*card*$) LOCAL I%, L%, N%, S% L% = LEN(*card*$) FOR I% = 1 TO L% N% = VAL(MID$(*card*$, L%-I% 1, 1)) IF I% AND 1 THEN S% = N% ELSE N% *= 2 S% = N% MOD 10 N% DIV 10 ENDIF NEXT = (S% MOD 10) = 0 ( luhn = sum odd even .

Val next dim check as integer = ( sum * 9 ) mod 10 return str( check )End Function Public Function Validate Mod10(digits As String) as Boolean dim check Digit as string = digits.