Sicher verschlüsseln Sie ganzzahlige (bis zu 2 ^ 48) in den kürzesten URL-sicheren String

In meiner Django-Anwendung habe ich hierarchische URL-Struktur:

webpage.com/property/PK/sub-property/PK/ etc …

Ich möchte keine Primärschlüssel aussetzen und eine Verwundbarkeit schaffen. Deshalb verschlade ich alle PKs in Strings in allen Vorlagen und URLs. Dies geschieht durch die wunderbare Bibliothek django-encrypted-id von diesem SO-Benutzer geschrieben. Allerdings unterstützt die Bibliothek bis zu 2 ^ 64 lange Integer und produziert 24 Zeichen Ausgabe (22 + 2 Polsterung). Dies führt zu riesigen URLs in meiner verschachtelten Struktur.

Deshalb möchte ich die verschlüsselten und entschlüsselnden Funktionen patch und versuchen, die Ausgabe zu verkürzen. Hier ist der Originalcode (+ padding Handling, den ich hinzugefügt habe):

 # Remove the padding after encode and add it on decode PADDING = '==' def encode(the_id): assert 0 <= the_id < 2 ** 64 crc = binascii.crc32(bytes(the_id)) & 0xffffff message = struct.pack(b"<IQxxxx", crc, the_id) assert len(message) == 16 cypher = AES.new( settings.SECRET_KEY[:24], AES.MODE_CBC, settings.SECRET_KEY[-16:] ) return base64.urlsafe_b64encode(cypher.encrypt(message)).rstrip(PADDING) def decode(e): if isinstance(e, basestring): e = bytes(e.encode("ascii")) try: e += str(PADDING) e = base64.urlsafe_b64decode(e) except (TypeError, AttributeError): raise ValueError("Failed to decrypt, invalid input.") for skey in getattr(settings, "SECRET_KEYS", [settings.SECRET_KEY]): cypher = AES.new(skey[:24], AES.MODE_CBC, skey[-16:]) msg = cypher.decrypt(e) crc, the_id = struct.unpack("<IQxxxx", msg) if crc != binascii.crc32(bytes(the_id)) & 0xffffff: continue return the_id raise ValueError("Failed to decrypt, CRC never matched.") # Lets test with big numbers for x in range(100000000, 100000003): ekey = encode(x) pk = decode(ekey) print "Pk: %s Ekey: %s" % (pk, ekey) 

Ausgabe (ich habe die Saiten ein bisschen gewechselt, also versuch nicht, mich zu hacken: P):

 Pk: 100000000 Ekey: GNtOHji8rA42qfq3p5gNMI Pk: 100000001 Ekey: tK6RcAZ2MrWmR3nB5qkQDe Pk: 100000002 Ekey: a7VXIf8pEB6R7XvqwGQo6W 

Ich habe versucht, alles in der encode() Funktion zu ändern, aber ohne Erfolg. Die produzierte Saite hat immer die Länge von 22.

Hier ist was ich will

  • Halten Sie die Verschlüsselungsstärke in der Nähe des ursprünglichen Levels oder zumindest nicht abnehmen dramatisch
  • Stützen Sie Integer bis zu 2 ^ 48 (~ 281 Billionen) oder 2 ^ 40, denn wie es jetzt mit 2 ^ 64 ist zu viel, denke ich nicht, dass wir jemals so große PKs in der Datenbank haben werden.
  • Ich werde mit String Länge zwischen 14-20 glücklich sein. Wenn seine 20 .. dann ja, seine noch 2 Zeichen weniger ..

One Solution collect form web for “Sicher verschlüsseln Sie ganzzahlige (bis zu 2 ^ 48) in den kürzesten URL-sicheren String”

Derzeit sind Sie mit CBC-Modus mit einem statischen IV, so dass der Code, den Sie haben, ist nicht sicher sowieso und, wie Sie sagen, produziert ziemlich große ciphertexts.

Ich würde empfehlen, Swapping aus CBC-Modus in CTR-Modus, mit denen Sie eine variable Länge IV haben können. Die normale empfohlene Länge für die IV (oder Nonce) im CTR-Modus, denke ich, ist 12, aber du kannst dies nach Bedarf reduzieren. CTR ist auch eine Stream-Chiffre, was bedeutet, was du hineinbringst, was du in der Größe bekommst. Mit AES, CBC-Modus wird immer zurückgeben Sie Ciphertexts in Blöcken von 16 Bytes so auch wenn Sie verschlüsseln 6 Bytes, erhalten Sie 16 Bytes aus, also ist nicht ideal für Sie.

Wenn Sie Ihre IV sagen … 48 Bits lang und zielen darauf ab, nicht größer als 48 Bits zu verschlüsseln, können Sie eine Rohausgabe von 6 + 6 = 12 Bytes oder mit base64 (4 * (12 / 3)) = 16 Bytes Sie können eine niedrigere Leistung als dies durch weitere Reduzierung Ihrer IV und / oder Eingabegröße (2 ^ 40?) Zu bekommen. Sie können mögliche Werte Ihrer Eingabe so weit senken, wie Sie wollen, ohne die Sicherheit zu beschädigen.

Denken Sie daran, dass CTR Fallstricke hat. Die Herstellung von zwei Ciphertexts, die das gleiche IV und Schlüssel teilen, bedeutet, dass sie trivial gebrochen werden können, also immer zufällig dein IV erzeugen (und es nicht in der Größe zu viel reduzieren).

  • Hashing (verstecken) Strings in Python
  • Verschlüsseln und Entschlüsseln mit PyCrypto AES 256
  • Wie 3DES in Python mit dem M2Crypto Wrapper verschlüsseln?
  • AES-Verschlüsselung in Node.js, um die erwartete Entschlüsselung in Python zu erfüllen
  • Vigenere cipher 'String Index außerhalb des Bereichs' für die Entschlüsselung
  • Verwenden Sie RSA, um in JavaScript zu verschlüsseln und in Python3 zu entschlüsseln
  • Python crypt in OSX
  • Verschlüsseln und Entschlüsseln durch AES-Algorithmus in Python und Android
  • Entschlüsseln einer Datei in einen Stream und Lesen des Streams in Pandas (hdf oder stata)
  • Warum ist AES verschlüsselte Chiffre der gleichen Saite mit der gleichen Taste immer anders?
  • Python-Code, der RSA verschlüsselte Datei in Chunks von 64 Bit unter Verwendung eines privaten Exponenten und Moduls entschlüsselt
  • Python ist die beste Programmiersprache der Welt.