CRACK Solution
Square Deal
CRACK sum-of-squares checksum keygen

Prerequisites
Unlocks
37213
Techniquesum-of-squares checksum keygen
Rulenonzero
Sample37213
Walkthrough
The check digit on this serial is not a tally and not a weighted tally. Each body digit is squared first, then the squares are summed and folded to one digit. Square, add, fold, and forge a serial that agrees with itself.
Check digit equals (sum of the squared body digits) mod 10. Square each of the four body digits, add them, reduce mod 10, and that is the fifth digit.
Hints
- HINT 1: The serial is five digits: four body digits and a check digit. Look at how each digit is multiplied by itself.
- HINT 2: Sum the four squares, then subtract 10 repeatedly until under 10. That remainder is the required check digit.
- HINT 3: For 3721 the squares are 9, 49, 4, 1 summing to 63, and 63 mod 10 is 3, so 37213 passes.
Reject Samples
- 37214
- 37212
- 37223
- 47213
- 3721
- 372130
- ABCDE
Verifier Listing
; z6_sumsq: "Square Deal". A serial validator whose check digit is not a plain
; sum and not a weighted sum: it is the sum of the SQUARES of the body digits,
; reduced mod 10. The serial is five ASCII digits, four body digits then a trailing
; check digit. Square each body digit (d times d), add the squares, reduce the
; total mod 10 by repeated subtraction, and the result must equal the check digit.
; Squaring is what makes a single wrong digit ripple: changing one body digit by
; one shifts its square by an odd amount, so the check mod 10 always moves. To
; crack it, pick a body, sum the squares, take mod 10, append it. Technique: sum-
; of-squares checksum keygen. r0 = 1 on accept; rule: nonzero.
;
; sample "37213": 3*3 + 7*7 + 2*2 + 1*1 = 9 + 49 + 4 + 1 = 63, 63 mod 10 = 3.
len r2
cmp r2, 5
jnz bad ; five ASCII digits: DDDD C
; every char must be a digit 0x30..0x39
mov r7, 0
dchk: cmp r7, 5
jge sum0
ldb r0, [r7]
cmp r0, 0x30
jl bad
cmp r0, 0x39
jg bad
inc r7
jmp dchk
; --- r3 = sum of squares of the 4 body digits, reduced mod 10: sum0: mov r3, 0
mov r7, 0
sloop: cmp r7, 4
jge final
ldb r0, [r7]
sub r0, 0x30 ; digit value 0..9
mov r6, r0
mul r6, r0 ; r6 = digit squared (max 81, fits a byte)
add r3, r6 ; running total (max so far well under 256)
red: cmp r3, 10 ; keep the total reduced mod 10
jl nextd
sub r3, 10
jmp red
nextd: inc r7
jmp sloop
; --- compare to the supplied check digit -----------------------
final: mov r7, 4
ldb r0, [r7]
sub r0, 0x30
cmp r0, r3
jnz bad
mov r0, 1
ret
bad: mov r0, 0
ret