DEV Community

Nathan Lucas
Nathan Lucas

Posted on

Don't Expose Your IDs: An Introduction to Obfuskey in Python

As developers, we often deal with integer IDs in our databases. They are simple, efficient, and great for internal use. But what happens when you expose these IDs to the outside world? A URL like your-app.com/post/1 followed by your-app.com/post/2 can give away a lot of information. It reveals the total number of posts, the rate at which new posts are created, and can even make it easier for malicious actors to scrape your data.


Where to Find Obfuskey

You can find the full source code, documentation, and open an issue on the project's GitHub repository. Obfuskey on GitHub


The Ecosystem of Reversible Obfuscation

Exposing a sequential primary key is a common practice, but it's not without its drawbacks. When choosing a solution to obfuscate these IDs, developers often consider a few popular options. Here’s a look at how Obfuskey compares to some of the key players in the Python ecosystem.

Alternative How it Works Pros Cons
Hashids Creates short, unique strings from integers based on a salt and alphabet. Keys are short, non-sequential, and human-friendly. Output length can vary with input magnitude. Less precise control over key length.
Sqids A modern, flexible alternative to Hashids for obfuscating multiple numbers. Keys are often shorter, more random-looking, and avoid separator characters. Also has variable output length depending on input magnitude.
ShortUUID Creates short, URL-safe versions of standard UUIDs. Keys are guaranteed to be unique and short. Great for shortening existing UUIDs. Not designed for obfuscating sequential integers; it shortens UUIDs, which are already non-sequential.
Obfuskey Reversible, non-cryptographic obfuscation of integers using a custom alphabet and fixed length. Reversible without a database lookup. Keys have a guaranteed fixed length. Full control over the character set. Not a cryptographic tool; should not be used for security-sensitive data.

Why Choose Obfuskey?

Obfuskey stands out for its clear API, precise control over a fixed-length output, and a core focus on reversible obfuscation. It provides a simple, robust solution without the overhead of more complex cryptographic or hashing libraries.


Getting Started with Obfuskey

First, let's install the library.

pip install obfuskey
Enter fullscreen mode Exit fullscreen mode

Now, let's see it in action. The core of Obfuskey is the Obfuskey class. When you instantiate it, you can specify the alphabet of characters to use and the desired key length.

For our first example, let's use the BASE56 alphabet, which is designed to be URL-safe and human-friendly by avoiding characters that can be easily confused, like 0 and O, or 1 and l.

from obfuskey import Obfuskey, alphabets

# Initialize Obfuskey with the BASE56 alphabet and a key length of 8
obfuscator = Obfuskey(alphabets.BASE56, key_length=8)

# Let's obfuscate an integer ID
original_id = 1234567890
obfuscated_key = obfuscator.get_key(original_id)

print(f"Original ID: {original_id}")       # 1234567890
print(f"Obfuscated Key: {obfuscated_key}") # SdkkpiUc

# Now, let's reverse the process
retrieved_id = obfuscator.get_value(obfuscated_key)

print(f"Retrieved ID: {retrieved_id}")     # 1234567890

# Let's see what happens with a different ID
another_id = 1234567891
another_key = obfuscator.get_key(another_id)

print(f"Another ID: {another_id}")         # 1234567891
print(f"Another Key: {another_key}")       # 5FvRbydm
Enter fullscreen mode Exit fullscreen mode

Notice how obfuscated_key and another_key are completely different, even though the original IDs are sequential. This is because Obfuskey uses a randomized mapping to ensure sequential inputs produce non-sequential outputs.


Customizing Your Obfuscation with Different Alphabets

Obfuskey provides several predefined alphabets for different use cases. You can choose one that best fits your needs, from short and compact to fully URL-safe.

For a very compact key that's perfect for internal APIs or systems where readability isn't a concern, you might use BASE64_URL_SAFE.

# Using a URL-safe Base64 alphabet for a shorter, more compact key
from obfuskey import Obfuskey, alphabets

compact_obfuscator = Obfuskey(alphabets.BASE64_URL_SAFE, key_length=6)

compact_key = compact_obfuscator.get_key(1001)
print(f"Compact Key (Base64): {compact_key}") # fkhvWj

compact_value = compact_obfuscator.get_value(compact_key)
print(f"Original Value: {compact_value}")     # 1001
Enter fullscreen mode Exit fullscreen mode

You can even create your own custom alphabet to perfectly match your brand or application's needs. The key is that every character in your custom alphabet must be unique, just like the digits in a number system.

# A custom alphabet using only a unique set of memorable characters
from obfuskey import Obfuskey

custom_alphabet = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefgh" # A unique 44-character alphabet
custom_obfuscator = Obfuskey(custom_alphabet, key_length=10)

custom_key = custom_obfuscator.get_key(987654321)
print(f"Custom Key: {custom_key}")       # MQ6gA5LPTT

custom_value = custom_obfuscator.get_value(custom_key)
print(f"Original Value: {custom_value}") # 987654321
Enter fullscreen mode Exit fullscreen mode

This level of customization gives you full control over the appearance and predictability of your obfuscated keys, allowing you to tailor them exactly to your use case.


Conclusion

The Obfuskey class is a powerful tool for obscuring sequential integer IDs into reversible, non-predictable keys. This simple pattern can dramatically improve the aesthetics and security-by-obscurity of your application's URLs and identifiers.

In the next article, we'll dive into an even more powerful feature of this package: Obfusbit, which allows you to pack multiple values into a single key, including large numbers like UUIDs.

Top comments (0)