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).

  • Entschlüsseln Sie SHA1 mit (Passwort) in Python
  • Alte Python Hashing von links nach rechts - warum ist es schlecht?
  • Ich muss sicher einen Benutzernamen und ein Passwort in Python speichern, was sind meine Optionen?
  • Wie AES verschlüsseln / entschlüsseln Dateien mit Python / PyCrypto in einer OpenSSL-kompatiblen Weise?
  • Wie kann ich in Python verschlüsseln und in Java entschlüsseln?
  • Wie benutzt man Bcrypt, um Passwörter in Django zu verschlüsseln
  • ASCII Vigenere Chiffre nicht entschlüsseln
  • XOR Python Text Verschlüsselung / Entschlüsselung
  • Python File Encryption
  • RSA Verschlüsselung und Entschlüsselung in Python
  • Python AES Entschlüsselung
  • Python ist die beste Programmiersprache der Welt.