1

I'm trying to hide database auto-incremented ids (1 to PHP_INT_MAX) from the user by encrypting the integer to another integer, making it appear random.

I considered doing an XOR

$mySecretNumber = 123456789;
$idToHide = 10;
$encryptedId = ($idToHide ^ $mySecretNumber);

but (I think) the secret number can easily be figured out.

How can I do this with a more secure method where I can specify a salt/password?

EDIT

To be clear, I need to (seemingly randomly) map an integer in the range 1 to PHP_INT_MAX to another integer in the same range.

Code
  • 6,041
  • 4
  • 35
  • 75
  • `trying to hide them` - can you elaborate on this? Surely changing your auto-incremented id's to some random encrypted number is not the right way to go. – Ohgodwhy Dec 24 '15 at 06:57
  • @Ohgodwhy I mean hide them when displaying it in the url or a REST api response. – Code Dec 24 '15 at 07:02
  • 1
    Why don't you use a real encryption function? – Barmar Dec 24 '15 at 07:05
  • Why does it have to map to an integer? Just use an encryption function, and then decrypt it when they send it back to the server. – Barmar Dec 24 '15 at 07:06
  • @Barmar It doesn't HAVE to be an integer; I just want it to be for simplicity and "cleanliness". Most big sites (e.g. facebook, twitter) use integers for their ids. – Code Dec 24 '15 at 07:07
  • 1
    Sure, but they're not trying to encrypt them. – Barmar Dec 24 '15 at 07:10
  • Why do you think the user will be able to figure out the secret number? He could do it if he knows any of the original IDs, but how would he find that out? – Barmar Dec 24 '15 at 07:12
  • @Barmar I'm not too sure about that.. but the mapping definitely doesn't appear random. – Code Dec 24 '15 at 07:21
  • If all your IDs are low numbers, they'll have the same high-order bits when you XOR them. So if you know that the original ID is less than 2^n, you can figure out all the bits of the secret number higher than nth order. – Barmar Dec 24 '15 at 07:25

3 Answers3

1

Are you trying to just obfuscate the ID number, e.g. for use in a URL? Encryption is the wrong tool for the "URL paremeter obfsucation" job.

Use a separate random value and maintain a server-side lookup of "random value"<->"integer" instead of encryption.

Unless you're a cryptography engineer with years of breaking crypto software under your belt (which most people asking these sorts of questions on Stack Overflow aren't), you should avoid implementing cryptography like the plague. You will almost certainly write vulnerable code before you've learned enough.

See also: Write crypto code! Don't publish it!

Scott Arciszewski
  • 33,610
  • 16
  • 89
  • 206
  • The reasons seem pretty one-sided. 1. Regarding security, it is not really needed. The purpose is to hide the ids from the average user. 2. Regarding "writing vulnerable code", the source codes of many algorithms are published online. – Code Dec 25 '15 at 04:19
  • Also, when using your method, why generate a random string when you can just generate a random integer/bigint, and then encode it if you want before outputting? – Code Dec 25 '15 at 05:03
  • @tumber033 Read this and then ask yourself if you think you can write crypto code that I can't break: https://paragonie.com/security -- step two: realize I'm not special and if I can break it, so can many people! – Scott Arciszewski Dec 25 '15 at 15:33
0

I solved this problem by using the TEA encryption algorithm (64-bit block cipher).

Note that the range isn't from 1 to PHP_INT_MAX but from PHP_INT_MIN to PHP_INT_MAX (for 64-bit PHP).

If you think there's anything wrong/bad with my method please let me know.

Also, I found 2 very useful topics on this: Obfuscating an ID, Symmetric Bijective Algorithm for Integers

EDIT

I chose the TEA algorithm simply because it's simple and fast and security is not a huge priority.

Community
  • 1
  • 1
Code
  • 6,041
  • 4
  • 35
  • 75
0

Any symmetric encryption in ECB mode would do it, as long as the block size is 64-bit and provided the key size is large enough, such as 112 for TDES or 128 for AES, but the range of the result would be the full 64 bits. But TEA is considered weak and therefor not suitable.

Jonathan Rosenne
  • 2,159
  • 17
  • 27
  • "But TEA is considered weak and therefor not suitable." So are: [ECB mode](https://blog.filippo.io/the-ecb-penguin), block ciphers with a block size < 128 bits, and unauthenticated encryption. I could conceive a chosen-ciphertext attack to SQL injection, in the worst case scenarios. – Scott Arciszewski Dec 26 '15 at 04:13
  • This is about encrypting a 64-bit number, not an arbitrary length text. ECB is the most suitable mode for this situation, the known weaknesses being irrelevant. Any other mode rather than ECB achieves nothing, because we have only a single block of input and thus there is no chaining. TDES, which has a block size of 64 bits and a key length of 112 bits is not considered weak for these types of usage. – Jonathan Rosenne Dec 27 '15 at 06:46
  • Okay, so then you advise someone to write their own crypto, and they open the door to chosen-ciphertext attacks and get pwned by a clever attacker. – Scott Arciszewski Dec 27 '15 at 08:55
  • @Scott. Please elaborate. I don't think this is what I have advised. – Jonathan Rosenne Dec 28 '15 at 19:36
  • 1. Keep sending garbage blocks instead of a real encrypted value. 2. Eventually decrypt a string like `X' or '1'='1' --` (two 64-bit blocks). 3. If this is blindly used to construct a MySQL query, you've just gotten SQLi on a chosen ciphertext. Unless you also authenticate your ciphertext, which increases the URL size. – Scott Arciszewski Dec 29 '15 at 03:02