Luhn mod N algoritmus - Luhn mod N algorithm

A Luhn mod N algoritmus a Luhn algoritmus (más néven mod 10 algoritmus) kiterjesztése, amely lehetővé teszi, hogy bármilyen bázis értéksorozataival dolgozzon . Ez akkor lehet hasznos, ha ellenőrző számra van szükség a betűkből, betűk és számok kombinációjából vagy tetszőleges N karakterből álló azonosító karakterlánc hitelesítéséhez.

Informális magyarázat

A Luhn mod N algoritmus egy ellenőrző számot (pontosabban egy ellenőrző karaktert) generál az érvényes karakterek ugyanazon tartományán belül, mint a beviteli karakterlánc. Például, ha az algoritmust kisbetűs ( az ) karakterláncokra alkalmazzák, akkor az ellenőrző karakter kisbetű is lesz. Ezen a különbségtételen kívül nagyon hasonlít az eredeti algoritmusra.

A kiterjesztés alapgondolata az, hogy az érvényes beviteli karakterek teljes készletét leképezzük a kódpontok (azaz a nullával kezdődő szekvenciális egész számok) listájára. Az algoritmus úgy dolgozza fel a bemeneti karakterláncot, hogy minden karaktert átalakít a hozzá tartozó kódponthoz, majd elvégzi a számításokat az N modban (ahol N az érvényes beviteli karakterek száma). Végül a kapott ellenőrző kódpontot visszaképezzük a megfelelő ellenőrző karakter megszerzéséhez.

Karakterek hozzárendelése kódpontokhoz

Először létre kell hozni az érvényes beviteli karakterek és a kódpontok leképezését. Vegyük például, hogy az érvényes karakter a kisbetűvel származó egy a f . Ezért megfelelő térképezés lenne:

karakter a b c d e f
Kód-pont 0 1 2 3 4 5.

Vegye figyelembe, hogy a karakterek sorrendje teljesen lényegtelen. Ez a másik leképezés is elfogadható (bár esetleg nehezebb megvalósítani):

karakter c e a f b d
Kód-pont 0 1 2 3 4 5.

Lehetőség van betűk és számjegyek (és esetleg más karakterek) keverésére is. Például ez a leképezés megfelelő lenne kisbetűs hexadecimális számjegyekhez:

karakter 0 1 2 3 4 5. 6. 7 8. 9. a b c d e f
Kód-pont 0 1 2 3 4 5. 6. 7 8. 9. 10. 11. 12. 13. 14 15

Algoritmus a C # számban

Feltéve, hogy a következő funkciók vannak meghatározva:

int CodePointFromCharacter(char character) {...}

char CharacterFromCodePoint(int codePoint) {...}

int NumberOfValidInputCharacters() {...}

Az ellenőrző karakter létrehozásának funkciója:

char GenerateCheckCharacter(string input)
{
    int factor = 2;
    int sum = 0;
    int n = NumberOfValidInputCharacters();

    // Starting from the right and working leftwards is easier since 
    // the initial "factor" will always be "2".
    for (int i = input.Length - 1; i >= 0; i--)
    {
        int codePoint = CodePointFromCharacter(input[i]);
        int addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = IntegerValue(addend / n) + (addend % n);
        sum += addend;
    }

    // Calculate the number that must be added to the "sum" 
    // to make it divisible by "n".
    int remainder = sum % n;
    int checkCodePoint = (n - remainder) % n;

    return CharacterFromCodePoint(checkCodePoint);
}

A karaktersorozat (a check karakterrel utolsó karakterként) érvényesítésének funkciója:

bool ValidateCheckCharacter(string input)
{
    int factor = 1;
    int sum = 0;
    int n = NumberOfValidInputCharacters();

    // Starting from the right, work leftwards
    // Now, the initial "factor" will always be "1" 
    // since the last character is the check character.
    for (int i = input.Length - 1; i >= 0; i--)
    {
        int codePoint = CodePointFromCharacter(input[i]);
        int addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = IntegerValue(addend / n) + (addend % n);
        sum += addend;
    }

    int remainder = sum % n;

    return (remainder == 0);
}

Algoritmus Java-ban

Feltéve, hogy a következő funkciók vannak meghatározva:

int codePointFromCharacter(char character) {...}

char characterFromCodePoint(int codePoint) {...}

int numberOfValidInputCharacters() {...}

Az ellenőrző karakter létrehozásának funkciója:

char generateCheckCharacter(String input) {
    int factor = 2;
    int sum = 0;
    int n = numberOfValidInputCharacters();

    // Starting from the right and working leftwards is easier since
    // the initial "factor" will always be "2".
    for (int i = input.length() - 1; i >= 0; i--) {
        int codePoint = codePointFromCharacter(input.charAt(i));
        int addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = (addend / n) + (addend % n);
        sum += addend;
    }

    // Calculate the number that must be added to the "sum"
    // to make it divisible by "n".
    int remainder = sum % n;
    int checkCodePoint = (n - remainder) % n;

    return characterFromCodePoint(checkCodePoint);
}

A karaktersorozat (a check karakterrel utolsó karakterként) érvényesítésének funkciója:

boolean validateCheckCharacter(String input) {
    int factor = 1;
    int sum = 0;
    int n = numberOfValidInputCharacters();

    // Starting from the right, work leftwards
    // Now, the initial "factor" will always be "1"
    // since the last character is the check character.
    for (int i = input.length() - 1; i >= 0; i--) {
        int codePoint = codePointFromCharacter(input.charAt(i));
        int addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = (addend / n) + (addend % n);
        sum += addend;
    }

    int remainder = sum % n;

    return (remainder == 0);
}

Algoritmus a JavaScript-ben

Feltéve, hogy a következő funkciók vannak meghatározva:

const codePoints = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//This can be any string of permitted characters

function numberOfValidInputCharacters() {
    return codePoints.length;
}

function codePointFromCharacter(character) {
    return codePoints.indexOf(character);
}

function characterFromCodePoint(codePoint) {
    return codePoints.charAt(codePoint);
}

Az ellenőrző karakter létrehozásának funkciója:

function generateCheckCharacter(input) {
    let factor = 2;
    let sum = 0;
    let n = numberOfValidInputCharacters();

    // Starting from the right and working leftwards is easier since
    // the initial "factor" will always be "2".
    for (let i = input.length - 1; i >= 0; i--) {
        let codePoint = codePointFromCharacter(input.charAt(i));
        let addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = (Math.floor(addend / n)) + (addend % n);
        sum += addend;
    }

    // Calculate the number that must be added to the "sum"
    // to make it divisible by "n".
    let remainder = sum % n;
    let checkCodePoint = (n - remainder) % n;
    return characterFromCodePoint(checkCodePoint);
}

A karaktersorozat (a check karakterrel utolsó karakterként) érvényesítésének funkciója:

function validateCheckCharacter(input) {
    let factor = 1;
    let sum = 0;
    let n = numberOfValidInputCharacters();

    // Starting from the right, work leftwards
    // Now, the initial "factor" will always be "1"
    // since the last character is the check character.
    for (let i = input.length - 1; i >= 0; i--) {
        let codePoint = codePointFromCharacter(input.charAt(i));
        let addend = factor * codePoint;

        // Alternate the "factor" that each "codePoint" is multiplied by
        factor = (factor == 2) ? 1 : 2;

        // Sum the digits of the "addend" as expressed in base "n"
        addend = (Math.floor(addend / n)) + (addend % n);
        sum += addend;
    }
    let remainder = sum % n;
    return (remainder == 0);
}

Példa

Generáció

Tekintsük a fenti érvényes beviteli karaktereket és az abcdef beviteli karakterláncot . Az ellenőrző karakter előállításához kezdje a karakterlánc utolsó karakterével, és lépjen balra duplázva minden más kódpontot. Ezután össze kell foglalni a 6. pontban leírt kódpontok "számjegyeit" (mivel 6 érvényes beviteli karakter van):

karakter a b c d e f
Kód-pont 0 1 2 3 4 5.
Kettős 2 6 (10. alap)
10 (6. alap)
10 (10. alap)
14 (6. alap)
Csökkentse 0 2 2 1 + 0 4 1 + 4
Számjegyek összege 0 2 2 1 4 5.

A számjegyek összege 14 (0 + 2 + 2 + 1 + 4 + 5). A szám, amelyet hozzá kell adni a következő 6-os (ebben az esetben 18 ) többszöröséhez, 4 . Ez az eredményül kapott ellenőrző kód-pont. A kapcsolódó ellenőrző karakter e .

Érvényesítés

Az így kapott abcdefe karakterlánc ezután egy hasonló eljárással érvényesíthető:

karakter a b c d e f e
Kód-pont 0 1 2 3 4 5. 4
Kettős 2 6 (10. alap)
10 (6. alap)
10 (10. alap)
14 (6. alap)
Csökkentse 0 2 2 1 + 0 4 1 + 4 4
Számjegyek összege 0 2 2 1 4 5. 4

A számjegyek összege 18 . Mivel osztható 6-tal, az ellenőrző karakter érvényes .

Végrehajtás

A karakterek hozzárendelése a kódpontokhoz és a visszafelé számos módon megvalósítható. A legegyszerűbb megközelítés (az eredeti Luhn-algoritmushoz hasonlóan) az ASCII kód-aritmetika használata. Például 0 és 9 közötti beviteli halmaz esetén a kódpont kiszámítható úgy, hogy kivonja a „0” ASCII kódját a kívánt karakter ASCII kódjából. A fordított művelet biztosítja a fordított leképezést. További karaktertartományok kezelhetők feltételes utasítások használatával.

A nem szekvenciális halmazok mindkét irányba leképezhetők egy hard-kódolt switch / case utasítás segítségével. Rugalmasabb megközelítés az asszociatív tömbhöz hasonló dolog használata . Ennek működéséhez pár tömbre van szükség a kétirányú leképezéshez.

További lehetőség a karakterek tömbjének használata, ahol a tömbindexek az egyes karakterekhez társított kódpontok. Ezután a karakterről kódpontra történő leképezés lineáris vagy bináris kereséssel végezhető el. Ebben az esetben a fordított leképezés csak egy egyszerű tömbkeresés.

Gyengeség

Ez a kiterjesztés ugyanazokkal a gyengeség, mint az eredeti algoritmus, azaz, hogy nem ismeri fel az átültetés a sorozat <első érvényes karakteres> <utolsó érvényes karakteres> a <utolsó érvényes karakteres> <első érvényes karakteres> (Vagy fordítva). Ez egyenértékű átültetése 09 és a 90 (feltételezve, hogy egy sor érvényes bemeneti karakterek 0 és 9- sorrendben). Pozitívum, hogy minél nagyobb az érvényes beviteli karakterkészlet, annál kisebb a gyengeség hatása.

Lásd még