22 октября 2012 г.

Генератор кредитных карт

Наткнулся тут на такой алгоритм под названием "Алгоритм Луна" который применяется для первичной верификации пластиковых банковских карт, а так же можно использовать для всяких медицинских страховок и прочих вещей где есть ручной ввод и человеческий фактор. Этот алгоритм защищает только от ошибочного ручного ввода, в любом случае банковская карта после этого проходит верификацию в процессинговом центре.

Так что AHTUNG! ALARM! ВНИМАНИЕ! генератор не работает и подсовывать с него номера пытаясь расплотиться в интернет магазинах - не надо, карта не сработает! Считайте, что я вас предупредил и любое использование этого генератора где то кроме изучения алгоритма - на свой страх и риск.
Для тех кто хочет узнать что за алгоритм и как написать программу для генерирования - под кат.

Итак, алгоритм достаточно прост и не замысловат:
1. Все цифры находящиеся на нечетной позиции в номере умножаются на 2
2. Сравниваем если получившиеся число больше 9 то отнимаем от него 9, если меньше то оставляем как есть
3. Складываем получившиеся цифры с теми которые находятся на четных позициях.
4. Если число делится на 10 без остатка - значит номер валидный, если нет - не валидный.
Вот в принципе и все, а теперь небольшой пример чтобы дошло:
имеем допустим следующий номер банковской карты:
4632 9471 3946 1396
считаем:
4 х 2 = 8 ->цифра меньше 9, оставлем как есть
6 - находится на четной позиции оставлем как есть
3 х 2 = 6 ->цифра меньше 9, оставлем как есть
2 - находится на четной позиции оставлем как есть
9 х 2 = 18, отнимаем 9 и получаем 9
4 - находится на четной позиции оставлем как есть
7 х 2 = 14, отнимаем 9 и получаем 5
1 - находится на четной позиции оставлем как есть
3 х 2 = 6 ->цифра меньше 9, оставлем как есть
9 - находится на четной позиции оставлем как есть
4 х 2 = ->цифра меньше 9, оставлем как есть
6 - находится на четной позиции оставлем как есть
1 х 2 = 2 ->цифра меньше 9, оставлем как есть
3 - находится на четной позиции оставлем как есть
9 х 2 = 18, отнимаем 9 и получаем 9
- находится на четной позиции оставлем как есть
А теперь складываем:
8+6+6+2+9+4+5+1+6+9+8+6+2+3+9+6 = 90
90 делится без остатка, значит номер кредитной банковской карты валидный.

Ну а теперь немножко говнокода :)
Я не буду приводить здесь листинг с коментами для всего кода программы, только части которая генерит номер кредиток:

CardGen proc uses eax ebx ecx ebp edx esi
    mov        sum, 0h ; в переменную sum пихаем ноль
    xor        esi, esi ; обнуляем esi
    xor        ebp, ebp ; обнуляем ebp
    mov        ecx, 0Fh ; в счетчик записываем колличество итераций
    lea        edi, cardNum ; в edi кладем указатель на начало строки с номером карты
nextint:
    invoke    random ; вызываем адскую функцию генерирующу рандомное число
    or         al, 0F0h ; выставляем старшие 4 байта в еденицу
    xor        al, 0F0h ; и обнуляем их
    .if    al >= 0Ah ; то что получилось больше либо равно 10?
        jmp        nextint ; попробуем еще раз
    .endif
    mov        BYTE PTR [edi], al ; записываем цифру получившуюся в строку с картой
    add        BYTE PTR [edi], 30h ; прибавляем 30h чтобы получить человеческую цифру
    inc        edi ; увеличим edi
    inc        esi ; увеличим esi
    bt        esi, 0 ; узнаем, позиция четная или нет?
    jae        chet ; если четная, приыгаем на метку chet
    shl        al, 1 ; умножаем то что в al на 2
    .if        al > 9 ; то что получилось больше 9?
        sub        al, 9 ; если больше, отнимаем 9
    .endif
chet:
    add        sum, al ; прибавляем то что получилось к цифре в переменной sum
    inc        ebp ; увеличим ebp
    .if        ebp == 4h ; ebp равно 4
        mov        BYTE PTR [edi], 20h ; вставим пробел для красоты
        inc        edi ; увеличим позицию в edi
        xor        ebp, ebp ; обнулим ebp
    .endif
    loop    nextint ; уходим на следующую итерацию пока ecx не станет == 0
    
    xor        eax, eax ; обнулим eax
    xor        edx, edx ; обнулим edx
    mov        al, sum ; поместим в al цифру получившуюся в al
    mov        ebx, 0Ah ; в ebx запихнем 10
    div        ebx ; поделим eax на ebx получив в edx остаток
    sub        ebx, edx ; отнимем от ebx edx чтобы получить контрольную цифру
    mov        BYTE PTR [edi], bl ; запишем ее последней в строчку
    add        BYTE PTR [edi], 30h ; прибавим 30h для получения человеческой цифры
    ret ; конец
CardGen endp

Кодъ целиком на pastebin.com тут.
Кодъ и скопиленная программа на deposite - тут.

Комментариев нет:

Отправить комментарий