Frage

Ich arbeite an einer Anwendung, bei der Benutzer einen Anruf tätigen und über die Tastatur ihres Telefons eine Bestätigungsnummer eingeben müssen.

Ich würde gerne erkennen können, ob die von ihnen eingegebene Nummer korrekt ist oder nicht.Das Telefonsystem hat keinen Zugriff auf eine Liste gültiger Nummern, sondern validiert die Nummer stattdessen anhand eines Algorithmus (z. B. einer Kreditkartennummer).

Hier sind einige der Anforderungen:

  • Es muss schwierig sein, einen gültigen Zufallscode einzugeben
  • Es muss schwierig sein, einen gültigen Code zu finden, wenn ich einen Tippfehler mache (Ziffern vertauscht, falsche Ziffer).
  • Ich muss eine angemessene Anzahl möglicher Kombinationen haben (sagen wir 1 Million).
  • Der Code muss so kurz wie möglich sein, um Fehler seitens des Benutzers zu vermeiden

Wie würden Sie angesichts dieser Anforderungen eine solche Zahl generieren?

BEARBEITEN :

@Haaked:Der Code muss numerisch sein, da der Benutzer ihn mit seinem Telefon eingibt.

@matt b:Im ersten Schritt wird der Code auf einer Webseite angezeigt, im zweiten Schritt erfolgt der Aufruf und die Eingabe des Codes.Ich kenne die Telefonnummer des Benutzers nicht.

Nachverfolgen :Ich habe mehrere Algorithmen dafür gefunden überprüfen die Gültigkeit von Zahlen (Siehe dieses interessante Google Code-Projekt: checkDigits).

War es hilfreich?

Lösung

Nach einiger Recherche denke ich, dass ich mich für das entscheiden werde ISO 7064 Mod 97,10 Formel.Es scheint ziemlich solide zu sein, da es zur Validierung der IBAN (International Bank Account Number) verwendet wird.

Die Formel ist ganz einfach:

  1. Zieh eine Nummer : 123456
  2. Wenden Sie die folgende Formel an, um die zweistellige Prüfsumme zu erhalten: mod(98 - mod(number * 100, 97), 97) => 76
  3. Concat-Nummer und Prüfsumme, um den Code zu erhalten => 12345676
  4. Um einen Code zu validieren, überprüfen Sie ihn mod(code, 97) == 1

Prüfen :

  • mod(12345676, 97) = 1 => GUT
  • mod(21345676, 97) = 50 => SCHLECHT!
  • mod(12345678, 97) = 10 => SCHLECHT!

Anscheinend fängt dieser Algorithmus die meisten Fehler ab.

Eine weitere interessante Option war die Verhoeff-Algorithmus.Sie hat nur eine Prüfziffer und ist schwieriger zu implementieren (im Vergleich zur einfachen Formel oben).

Andere Tipps

Für 1M-Kombinationen benötigen Sie 6 Ziffern.Um sicherzustellen, dass es keine versehentlich gültigen Codes gibt, empfehle ich 9 Ziffern mit einer Chance von 1/1000, dass ein zufälliger Code funktioniert.Ich würde auch vorschlagen, eine andere Ziffer (insgesamt 10) zu verwenden, um eine durchzuführen Integritätsprüfung.Bei den Verteilungsmustern reicht der Zufall aus und die Prüfziffer stellt sicher, dass ein einzelner Fehler nicht zu einem korrekten Code führt.

Bearbeiten: Anscheinend habe ich Ihre Anfrage nicht vollständig gelesen.Mithilfe einer Kreditkartennummer könnten Sie darauf einen Hash durchführen (MD5 oder SHA1 oder ähnliches).Anschließend kürzen Sie an einer geeigneten Stelle (z. B. 9 Zeichen) und konvertieren zur Basis 10.Dann fügen Sie die Prüfziffer(n) hinzu und dies sollte für Ihre Zwecke mehr oder weniger funktionieren.

Sie möchten Ihren Code segmentieren.Ein Teil davon sollte ein 16-Bit-CRC des restlichen Codes sein.

Wenn Sie lediglich eine Verifizierungsnummer benötigen, verwenden Sie einfach eine Sequenznummer (vorausgesetzt, Sie haben einen einzigen Generierungspunkt).Auf diese Weise wissen Sie, dass Sie keine Duplikate erhalten.

Dann stellen Sie der Sequenz einen CRC-16 dieser Sequenznummer UND einen privaten Schlüssel voran.Für den privaten Schlüssel können Sie alles verwenden, solange Sie ihn privat halten.Machen Sie es zu etwas Großem, zumindest einem GUID, aber es könnte der Text sein Krieg und Frieden aus dem Projekt Gutenberg.Es muss nur geheim und konstant sein.Ein privater Schlüssel verhindert, dass jemand einen Schlüssel fälschen kann, aber die Verwendung eines 16-Bit-CR macht es einfacher, ihn zu knacken.

Zur Validierung teilen Sie einfach die Nummer in zwei Teile auf und nehmen dann einen CRC-16 der Sequenznummer und des privaten Schlüssels.

Wenn Sie den sequentiellen Teil stärker verdecken möchten, teilen Sie den CRC in zwei Teile auf.Fügen Sie drei Ziffern vorne und zwei Ziffern hinten in die Sequenz ein (Nullen auffüllen, damit die Länge des CRC konsistent ist).

Mit dieser Methode können Sie auch mit kleineren Schlüsseln beginnen.Die ersten 10 Schlüssel sind 6-stellig.

Müssen es nur Zahlen sein?Sie könnten eine Zufallszahl zwischen 1 und 1 Million erstellen (ich würde jedoch sogar noch höher vorschlagen) und dann Base32 kodieren Sie es.Als nächstes müssen Sie diesen Wert hashen (unter Verwendung eines geheimen Salt-Werts) und den Hash mit Base32 kodieren.Hängen Sie dann die beiden Zeichenfolgen aneinander, möglicherweise getrennt durch den Bindestrich.

Auf diese Weise können Sie den eingehenden Code algorithmisch überprüfen.Sie nehmen einfach die linke Seite des Codes, hashen ihn mit Ihrem geheimen Salt und vergleichen diesen Wert mit der rechten Seite des Codes.

  • Ich muss eine angemessene Anzahl möglicher Kombinationen haben (sagen wir 1 Million)
  • Der Code muss so kurz wie möglich sein, um Fehler seitens des Benutzers zu vermeiden

Nun, wenn Sie möchten, dass es mindestens eine Million Kombinationen gibt, dann brauchen Sie mindestens sechs Ziffern.Ist das kurz genug?

Haben Sie beim Erstellen des Bestätigungscodes Zugriff auf die Telefonnummer des Anrufers?

Wenn ja, würde ich die Telefonnummer des Anrufers verwenden und sie durch eine Art Hashing-Funktion laufen lassen, damit Sie garantieren können, dass der Bestätigungscode, den Sie dem Anrufer in Schritt 1 gegeben haben, derselbe ist, den er in Schritt 2 eingegeben hat (um sicherzugehen). sie verwenden nicht den Validierungscode eines Freundes oder sie haben einfach eine sehr glückliche Vermutung gemacht).

Was das Hashing angeht, bin ich mir nicht sicher, ob es möglich ist, eine 10-stellige Zahl zu nehmen und ein Hash-Ergebnis zu erhalten, das < 10 Ziffern wäre (ich schätze, man müsste mit einem gewissen Maß an Kollision leben), aber ich denke Dies würde dazu beitragen, sicherzustellen, dass der Benutzer der ist, für den er sich ausgibt.

Dies funktioniert natürlich nicht, wenn die in Schritt 1 verwendete Telefonnummer eine andere ist als die, von der aus Sie in Schritt 2 anrufen.

Vorausgesetzt, Sie wissen bereits, wie Sie erkennen, welche Taste der Benutzer gedrückt hat, sollte dies einigermaßen einfach zu bewerkstelligen sein.In der Welt der Sicherheit gibt es den Begriff eines „Einmalpassworts“.Dies wird manchmal als "Einwegkennwort" bezeichnet. Normalerweise sind diese auf die (leicht typbaren) ASCII -Werte beschränkt.Also [a-zA-z0-9] und eine Reihe leicht typisierbarer Symbole.wie Komma, Punkt, Semikolon und Klammer.In Ihrem Fall möchten Sie den Bereich jedoch wahrscheinlich auf [0-9] beschränken und möglicherweise * und # einschließen.

Ich kann nicht alle technischen Details zur Generierung (oder Funktionsweise) dieser Einmalcodes angemessen erläutern.Dahinter steckt eine Zwischenstufe, die ich verwerfen würde, ohne sie vorher selbst durchzugehen.Es genügt zu sagen, dass Sie einen Algorithmus verwenden, um einen Strom von Einmalpasswörtern zu generieren.Ganz gleich, wie viele vorherige Codes Sie kennen, der nächste sollte unmöglich zu erraten sein!In Ihrem Fall verwenden Sie einfach jedes Passwort in der Liste als Zufallscode des Benutzers.

Anstatt es zu versäumen, die Details der Implementierung selbst zu erklären, verweise ich Sie auf einen 9-seitigen Artikel, in dem Sie selbst nachlesen können: https://www.grc.com/ppp.htm

Es hört sich so an, als hätten Sie die unausgesprochene Anforderung, dass mithilfe eines Algorithmus schnell festgestellt werden muss, dass der Code gültig ist.Dies würde es ausschließen, dass Sie einfach eine Liste mit einmaligen Pad-Nummern verteilen.

Es gibt verschiedene Möglichkeiten, wie Menschen dies in der Vergangenheit getan haben.

  1. Erstellen Sie einen öffentlichen und einen privaten Schlüssel.Verschlüsseln Sie die Zahlen 0-999.999 mit dem privaten Schlüssel und verteilen Sie die Ergebnisse.Sie müssen einige Zufallszahlen eingeben, damit das Ergebnis in der längeren Version angezeigt wird, und Sie müssen das Ergebnis von der Basis 64 in die Basis 10 umwandeln.Wenn Sie eine Zahl eingegeben haben, konvertieren Sie sie zurück in Base64, wenden Sie den privaten Schlüssel an und prüfen Sie, ob die interessanten Zahlen unter 1.000.000 liegen (verwerfen Sie die Zufallszahlen).
  2. Benutze einen reversible Hash-Funktion
  3. Verwenden Sie die ersten Millionen Zahlen aus einem PRN, der auf einen bestimmten Wert gesetzt ist.Die Funktion „Prüfung“ kann den Startwert abrufen und wissen, dass die nächsten Millionen Werte gut sind.Es kann sie entweder jedes Mal generieren und einzeln überprüfen, wenn ein Code empfangen wird, oder sie beim Programmstart alle in einer Tabelle speichern, sortieren und dann die binäre Suche (maximale Vergleiche) verwenden, da eine Million Ganzzahlen keine ganze Menge ist Raum.

Es gibt eine Reihe anderer Optionen, diese sind jedoch weit verbreitet und einfach zu implementieren.

-Adam

Du hast mit dem verlinkt Prüfziffern Projekt, und die Verwendung der Funktion „encode“ scheint eine gute Lösung zu sein.Es sagt:

encode kann eine Ausnahme auslösen, wenn „schlechte“ Daten (z. B.nicht numerisch) übergeben, während „Verify“ nur „true“ oder „false“ zurückgibt.Der Grundgedanke dabei ist, dass encode seine Daten normalerweise aus „vertrauenswürdigen“ internen Quellen (z. B. einem Datenbankschlüssel) bezieht, sodass es ziemlich üblich, ja sogar die Ausnahme sein sollte, dass fehlerhafte Daten weitergegeben werden.

Es hört sich also so an, als könnten Sie der Verschlüsselungsfunktion einen Datenbankschlüssel (z. B. 5 Ziffern) übergeben und eine Nummer erhalten, die Ihren Anforderungen entspricht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top