Ich suche nach einer Möglichkeit, eine Ganzzahl-ID in eine andere Ganzzahl zu verschlüsseln / zu verschleiern. Genauer gesagt, ich brauche eine Funktion int F(int x)
, damit
- x <-> F (x) ist eine Eins-zu-Eins-Entsprechung (wenn x! = y, F (x)! = F (y))
- Wenn F (x) gegeben ist, ist es einfach, x herauszufinden - F ist also keine Hash-Funktion
- Bei x und F (x) ist es schwer / unmöglich, F (y) herauszufinden, so etwas
x ^ 0x1234
funktioniert nicht
Aus Gründen der Klarheit suche ich keine starke Verschlüsselungslösung, sondern nur eine Verschleierung. Stellen Sie sich eine Web - Anwendung mit Urls wie example.com/profile/1
, example.com/profile/2
usw. Die Profile selbst nicht geheim sind, aber ich würde gerne lässig Voyeure Ansicht verhindern / holen alle Profile nacheinander, so dass ich sie lieber hinter etwas verstecken würde wie example.com/profile/23423
, example.com/profile/80980234
usw. Obwohl In der Datenbank gespeicherte Token können die Arbeit ganz einfach erledigen. Ich bin gespannt, ob dafür eine einfache Mathematik verfügbar ist.
Eine wichtige Anforderung war ich nicht klären ist , dass die Ergebnisse aussehen sollten „random“, das heißt, da eine Sequenz x,x+1,...,x+n
, F(x),F(x+1)...F(x+n)
sollte kein Fortschreiten jeglicher Art bilden.
quelle
Antworten:
Verschleiern Sie es mit einer Kombination aus 2 oder 3 einfachen Methoden:
x
undy
die multiplikative Inverse zueinander (Modulo 2 32 ), dann multiplizieren mitx
zu verschleiern und vermehren sich durchy
die Wiederherstellung sind alle Multiplikationen modulo 2 32 (Quelle: „Eine praktische Anwendung der multiplikativen Umkehrungen“ von Eric Lippert )Die numerische Systemmethode mit variabler Länge entspricht nicht allein Ihrer "Progressions" -Anforderung. Es werden immer kurze arithmetische Progressionen erzeugt. In Kombination mit einer anderen Methode ergeben sich jedoch gute Ergebnisse.
Gleiches gilt für die modulare Darstellungsmethode.
Hier ist ein C ++ - Codebeispiel für 3 dieser Methoden. Beispiel für Shuffle-Bits können verschiedene Masken und Entfernungen verwenden, um unvorhersehbarer zu sein. Andere 2 Beispiele sind gut für kleine Zahlen (nur um die Idee zu geben). Sie sollten erweitert werden, um alle ganzzahligen Werte richtig zu verschleiern.
quelle
Sie möchten, dass die Transformation reversibel und nicht offensichtlich ist. Das klingt nach einer Verschlüsselung, die eine Zahl in einem bestimmten Bereich akzeptiert und eine andere Zahl im gleichen Bereich erzeugt. Wenn Ihr Bereich 64-Bit-Zahlen umfasst, verwenden Sie DES. Wenn Ihr Bereich 128-Bit-Zahlen beträgt, verwenden Sie AES. Wenn Sie einen anderen Bereich wünschen, ist Ihre wahrscheinlich beste Wahl die Hasty Pudding-Chiffre , die für unterschiedliche Blockgrößen und Nummernkreise ausgelegt ist, die nicht genau in einen Block passen, z. B. 100.000 bis 999.999.
quelle
Die Verschleierung ist aus Sicherheitsgründen nicht ausreichend.
Wenn Sie jedoch versuchen, den zufälligen Betrachter zu vereiteln, würde ich eine Kombination aus zwei Methoden empfehlen:
Hier ist ein Beispiel (unter Verwendung von Pseudocode):
Ich habe es nicht getestet, aber ich denke, das ist reversibel, sollte schnell sein und nicht zu einfach, um die Methode zu testen.
quelle
return x XOR rotr(31415927, 5)
, oder? Das letzte xor macht das erste rückgängig und das Drehen macht sich gegenseitig rückgängig. Natürlich ist jede Kette von reversiblen Operationen auch reversibel, so dass es diese Bedingung erfüllt.x = x XOR F(0)
, oderx = x XOR 3087989491
, oderx = x XOR rotr(31415927, 5)
. Ihr erster und letzter Xor negieren sich gegenseitig. Sie müssen also nur die bitverschobene Eingabe mit der Taste xorieren - oder gleichwertig die Eingabe mit der bitverschobenen Taste xoring. Beachten Sie, dass dies auch dann zutrifft, wenn Sie für jede Stufe unterschiedliche Schlüssel verwendet haben. Alle Schlüssel können zu einem einzigen Schlüssel zusammengesetzt werden, der mit dem Klartext xored werden kann.Ich fand diesen speziellen Python / PHP-Code sehr nützlich:
https://github.com/marekweb/opaque-id
quelle
Ich habe JS-Code mit einigen der Ideen in diesem Thread geschrieben:
Es liefert einige schöne Ergebnisse wie:
Testen mit:
XOR1
undXOR2
sind nur Zufallszahlen zwischen 0 undMAX
.MAX
ist2**32-1
; Sie sollten dies auf das einstellen, was Ihrer Meinung nach Ihre höchste ID sein wird.COPRIME
ist eine Zahl, die Koprime w /MAX
. ich denke, Primzahlen selbst sind Koprime mit jeder anderen Zahl (außer Vielfachen von sich selbst).INVERSE
ist die schwierige Frage. Diese Blog-Beiträge geben keine klare Antwort, aber WolframAlpha kann es für Sie herausfinden . Lösen Sie einfach die Gleichung(COPRIME * x) % MAX = 1
fürx
.Die
build
Funktion wurde von mir erstellt, um das Erstellen dieser Codierungs- / Decodierungs-Pipelines zu vereinfachen. Sie können beliebig viele Operationen als[encode, decode]
Paare eingeben. Diese Funktionen müssen gleich und entgegengesetzt sein. DasXOR
Funktionen sind ihre eigenen Komplimente, so dass Sie dort kein Paar benötigen.Hier ist eine weitere lustige Involution :
(geht von 24-Bit-Ganzzahlen aus - ändern Sie einfach die Zahlen für eine andere Größe)
quelle
n
ist ein Postfix für BigInts . Es ist eine neue JS-Funktion, mit der Sie wirklich große Zahlen verarbeiten können. Ich musste es verwenden, weil ich mit wirklich großen Zahlen multipliziere, was dazu führen kann, dass einer der Zwischenwerte vorübergehend dieNumber.MAX_SAFE_INTEGER
Genauigkeit überschreitet und verliert.Machen Sie alles mit den Bits der ID, die sie nicht zerstören. Beispielsweise:
Führen Sie dies zur Entschlüsselung in umgekehrter Reihenfolge durch.
Erstellen Sie ein Programm, das einige interessante Werte für Sie "verschlüsselt" und in eine Tabelle einfügt, die Sie untersuchen können. Lassen Sie dasselbe Programm Ihre Verschlüsselungs- / Entschlüsselungsroutine mit allen Werten testen, die Sie in Ihrem System haben möchten.
Fügen Sie der obigen Liste Dinge zu den Routinen hinzu, bis Ihre Zahlen für Sie richtig verstümmelt aussehen.
Für alles andere erhalten Sie eine Kopie des Buches .
quelle
Ich habe einen Artikel über sichere Permutationen mit Blockchiffren geschrieben , der Ihre Anforderungen wie angegeben erfüllen sollte.
Ich würde jedoch vorschlagen, dass Sie, wenn Sie schwer zu erratende Bezeichner möchten, diese zunächst verwenden sollten: Generieren Sie UUIDs und verwenden Sie diese zunächst als Primärschlüssel für Ihre Datensätze - Sie müssen nicht in der Lage sein in und von einer "echten" ID konvertieren.
quelle
Ich bin mir nicht sicher, wie "hart" es sein muss, wie schnell oder wie wenig Speicher verwendet werden soll. Wenn Sie keine Speicherbeschränkungen haben, können Sie eine Liste aller Ganzzahlen erstellen, diese mischen und diese Liste als Zuordnung verwenden. Selbst für eine 4-Byte-Ganzzahl würden Sie jedoch viel Speicher benötigen.
Dies könnte jedoch kleiner gemacht werden, sodass Sie anstelle der Zuordnung aller Ganzzahlen nur 2 (oder im schlimmsten Fall 1) Byte zuordnen und diese auf jede Gruppe in der Ganzzahl anwenden würden. Wenn Sie also 2 Bytes verwenden, wäre eine Ganzzahl (Gruppe1) (Gruppe2). Sie würden jede Gruppe durch die zufällige Zuordnung zuordnen . Dies bedeutet jedoch, dass die Zuordnung für Gruppe1 gleich bleibt, wenn Sie nur Gruppe2 ändern. Dies könnte "behoben" werden, indem jeder Gruppe unterschiedliche Bits zugeordnet werden.
Also könnte * (Gruppe2) sein (Bit 14,12,10,8,6,4,2,0), also würde das Hinzufügen von 1 sowohl Gruppe1 als auch Gruppe2 ändern .
Dies ist jedoch nur Sicherheit durch Unbekanntheit. Jeder, der Zahlen in Ihre Funktion einspeisen kann (selbst wenn Sie die Funktion geheim halten), kann dies ziemlich leicht herausfinden.
quelle
Generieren Sie einen privaten symmetrischen Schlüssel zur Verwendung in Ihrer Anwendung und verschlüsseln Sie Ihre Ganzzahl damit. Dies wird alle drei Anforderungen erfüllen, einschließlich der schwierigsten Nr. 3: Man müsste Ihren Schlüssel erraten, um Ihr Schema zu brechen.
quelle
Was Sie hier beschreiben, scheint das Gegenteil einer Einwegfunktion zu sein: Es ist leicht zu invertieren, aber sehr schwierig anzuwenden. Eine Möglichkeit wäre die Verwendung eines Standardverschlüsselungsalgorithmus für öffentliche Schlüssel von der Stange, bei dem Sie einen (geheimen, zufällig ausgewählten) öffentlichen Schlüssel festlegen, den Sie geheim halten, und einen privaten Schlüssel, den Sie mit der Welt teilen. Auf diese Weise wäre Ihre Funktion F (x) die Verschlüsselung von x mit dem öffentlichen Schlüssel. Mit dem privaten Entschlüsselungsschlüssel können Sie dann F (x) problemlos wieder nach x entschlüsseln. Beachten Sie, dass die Rollen des öffentlichen und des privaten Schlüssels hier vertauscht sind. Sie geben den privaten Schlüssel an alle weiter, damit diese die Funktion entschlüsseln können, aber den öffentlichen Schlüssel auf Ihrem Server geheim halten. Dieser Weg:
Das hat viele Vorteile. Erstens können Sie sicher sein, dass das Kryptosystem sicher ist, denn wenn Sie einen etablierten Algorithmus wie RSA verwenden, müssen Sie sich keine Sorgen über versehentliche Unsicherheit machen. Zweitens gibt es bereits Bibliotheken, die dies tun. Sie müssen also nicht viel programmieren und können gegen Seitenkanalangriffe immun sein. Schließlich können Sie es jedem ermöglichen, F (x) zu invertieren, ohne dass jemand tatsächlich F (x) berechnen kann.
Ein Detail - Sie sollten hier definitiv nicht nur den Standard-Int-Typ verwenden. Selbst bei 64-Bit-Ganzzahlen sind so wenige Kombinationen möglich, dass ein Angreifer nur mit brutaler Gewalt versuchen kann, alles umzukehren, bis er für einige y die Verschlüsselung F (y) findet, selbst wenn er nicht über den Schlüssel verfügt. Ich würde vorschlagen, so etwas wie einen 512-Bit-Wert zu verwenden, da selbst ein Science-Fiction-Angriff dies nicht brutal erzwingen könnte.
Hoffe das hilft!
quelle
Wenn
xor
es für alles akzeptabel ist, aber darauf schließenF(y)
,x
undF(x)
dann denke ich, dass Sie das mit einem Salz tun können . Wählen Sie zuerst eine geheime Einwegfunktion. Zum BeispielS(s) = MD5(secret ^ s)
. Dann ,F(x) = (s, S(s) ^ x)
wos
wird zufällig ausgewählt. Ich habe das als Tupel geschrieben, aber Sie können die beiden Teile zu einer ganzen Zahl kombinieren, zF(x) = 10000 * s + S(s) ^ x
. Die Entschlüsselung extrahiert das Salzs
wieder und verwendetF'(F(x)) = S(extract s) ^ (extract S(s)^x)
. Gegebenx
undF(x)
Sie können sehens
(obwohl es leicht verschleiert ist) und Sie können schließen,S(s)
aber für einen anderen Benutzery
mit einem anderen zufälligen Salz,t
den der BenutzerF(x)
nicht finden kannS(t)
.quelle
S(s)
wird auch zufällig aussehen, soF(x)
dass überhaupt keine Progression auftritt.