0

Is it possible to encode user's ID# to text value?

For example if the user ID# is '50624' is it possible to convert it to 7 characters text value, something like 'DEGXCVG'?

If I use MD5 for this function I get 16-byte hash value. The result value should not be longer than 7 or 8 characters.

Edit: I want that each user has a different text code obtained from the id number.

hakre
  • 193,403
  • 52
  • 435
  • 836
Sergio
  • 1,207
  • 7
  • 28
  • 42

6 Answers6

2

Try changing the integer into a Hexadecimal value using dechex

Anyway if u able to explain your scenario more clear, we may able to provide best solution

Vijay
  • 5,331
  • 10
  • 54
  • 88
  • @gumbo Yes, since i didn't know his exact requirement, i just suggested a encoded solution. Thanks for your comment. :) – Vijay May 28 '11 at 12:27
1

What are you trying to accomplish with this?

First of all MD5 is not "encryption" it is a one-way hash function. It cannot be reversed. If that is OK for you, why not simply hash your IDs and then take 7-8 characters from the hash? You could MD5 your ID and then take the first 8 characters of the resulting MD5.

defines
  • 10,229
  • 4
  • 40
  • 56
  • In that case, if I use first 7 characters from hash, what are the chances that some other user have the same hash code? I want that each user has a different text code obtained from the id number. – Sergio May 28 '11 at 12:20
  • It's very unlikely but not impossible that 2 users would have the same value. You might be better off converting your int to its hexadecimal string equivalent. Any time you are casting a something into a fixed width you necessarily have a FINITE number of possible outputs, so there is no way to map an infinite number of inputs to a finite number of outputs WITHOUT a repeating value (collision). – defines May 28 '11 at 12:22
1

what you are looking for is called base transformation ... your ID is a base 10 number with the numbers from 0 to 9 represent the digits of that base.

other common bases would be 2 (binary), 16(hexadecimal), or 64(often called base 64 encoding) but you could also take some other base if you like.

i've written a somewhat general base transform code in c# (uint to whatever base string and vice versa) ... shouldn't be that hard to port it to php:

static void Main(string[] args)
{
    foreach (var item in UintToOtherBase(0xDEADBEEF, "01").Reverse())
    {
        Console.Write(item);
    }
    Console.WriteLine();
    Console.WriteLine(OtherBaseToInt(UintToOtherBase(0xDEADBEEF, "01"), "01").ToString("X"));
    Console.WriteLine(UintToOtherBase(0xDEADBEEF, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
}

public static string UintToOtherBase(uint input, string newBaseDigits)
{
    char[] uniqueDigits = newBaseDigits.ToCharArray().Distinct().ToArray();
    uint newBase = (uint)uniqueDigits.Length;
    if (newBase < 2)
    {
        throw new ArgumentException("otherBaseDigits has to contain at least 2 unique chars");
    }
    else
    {
        StringBuilder sb = new StringBuilder();
        while (input != 0)
        {
            uint digit = input % newBase;
            sb.Append(uniqueDigits[digit]);
            input /= newBase;
        }
        return sb.ToString();
    }
}
public static uint OtherBaseToInt(string input, string otherBaseDigits)
{
    string uniqueDigits = new String(otherBaseDigits.ToCharArray().Distinct().ToArray());
    int otherBase = uniqueDigits.Length;
    if (otherBase < 2)
    {
        throw new ArgumentException("otherBaseDigits has to contain at least 2 unique chars");
    }
    else if (input.ToCharArray().Any(x => !uniqueDigits.Contains(x)))
    {
        throw new ArgumentException("an input char was not found in otherBaseDigits");
    }
    else
    {
        uint result = 0;
        int pow = 0;
        foreach (var c in input)
        {
            result += (uint)uniqueDigits.IndexOf(c) * (uint)Math.Pow(otherBase, pow++);
        }
        return result;
    }
}

//edit:

but just to point it out, this is an encoding ... no encryption

DarkSquirrel42
  • 10,167
  • 3
  • 20
  • 31
1

If a hash function such as MD5 can be used instead of encryption, you could try crc32() instead, which produces shorter (but with much higher chances of collisions) strings.


If you just care about encoding, you could do something simpler:

function encode($id) {
  $id_str = (string) $id;
  $offset = rand(0, 9);
  $encoded = chr(79 + $offset);
  for ($i = 0, $len = strlen($id_str); $i < $len; ++$i) {
    $encoded .= chr(65 + $id_str[$i] + $offset);
  }
  return $encoded;
}

function decode($encoded) {
  $offset = ord($encoded[0]) - 79;
  $encoded = substr($encoded, 1);
  for ($i = 0, $len = strlen($encoded); $i < $len; ++$i) {
    $encoded[$i] = ord($encoded[$i]) - $offset - 65;
  }
  return (int) $encoded;
}

Example:

var_dump(encode(50624)); // string(6) "TKFLHJ"

Encryption version:

define('CRYPTO_KEY', 'Secret key');

function encrypt($id) {
  return base64_encode(mcrypt_encrypt(MCRYPT_BLOWFISH, CRYPTO_KEY, (string) $id, MCRYPT_MODE_ECB));
}

function decrypt($encrypted) {
  return (int) base64_decode(mcrypt_decrypt(MCRYPT_BLOWFISH, CRYPTO_KEY, $encrypted, MCRYPT_MODE_ECB));
}
rid
  • 61,078
  • 31
  • 152
  • 193
  • @rdineiu - This is nice solution. But I get some strange characters as result. What can be the problem? – Sergio May 28 '11 at 12:36
  • @Sergio, it's the encrypted string. Encode it with something like `base64_encode()` or `urlencode()`. Check out the last part of the example. – rid May 28 '11 at 12:36
  • @rdineiu - I did that but I get varchar value. I need result value without numbers. – Sergio May 28 '11 at 12:41
  • @Sergio, if you call `base64_encode(encrypt(50624))` you will get the string `MCLLRJooaoQ=`. Is this not what you want? – rid May 28 '11 at 12:45
  • @rdineiu - yes, but for base64_encode(encrypt(50625)) I get 'SR2rpy5Ij00='. I don't want numbers in result value. – Sergio May 28 '11 at 12:53
  • @Sergio, I see. I added an encoding option to the examples as well. It won't have any number in it. It's not encrypted or secure either. – rid May 28 '11 at 12:55
  • Also, the first method, with encryption, won't work, because you need to send the $iv as well, which will make the string 16 bytes. Removed the example. – rid May 28 '11 at 13:03
  • @rdineiu - The encryption method was fine if I can find the solution for result value length (max 7 characters) and to remove numbers from it. – Sergio May 28 '11 at 13:09
  • @Sergio, can't really do much to get the size to max. 7 characters with encryption. – rid May 28 '11 at 13:14
0

If obscuring is good enough, convert the number to base62 after permuting its bits.

Denis de Bernardy
  • 75,850
  • 13
  • 131
  • 154
0

I think you can design your own encryption method or take part of md5 hash value.
Btw, the way to encrypt an integer has been discussed in the following post.

Way to encrypt a single int

Community
  • 1
  • 1
YeJiabin
  • 1,038
  • 1
  • 9
  • 17