I'm not sure what this is called, which is why I'm having trouble searching for it.
What I'm looking to do is to take numbers and convert them to some alphanumeric base so that the number, say 5000, wouldn't read as '5000' but as 'G4u', or something like that. The idea is to save space and also not make it obvious how many records there are in a given system. I'm using php, so if there is something like this built into php even better, but even a name for this method would be helpful at this point.
Again, sorry for not being able to be more clear, I'm just not sure what this is called.
You want to change the base of the number to something other than base 10 (I think you want base 36 as it uses the entire alphabet and numbers 0 - 9).
The inbuilt base_convert function may help, although it does have the limitation it can only convert between bases 2 and 36
$number = '5000';
echo base_convert($number, 10, 36); //3uw
Funnily enough, I asked the exact opposite question yesterday.
The first thing that comes to mind is converting your decimal number into hexadecimal. 5000 would turn into 1388, 10000 into 2710. Will save a few bytes here and there.
You could also use a higher base that utilizes the full alphabet (0-Z instead of 0-F) or even the full 256 ASCII characters. As #Yacoby points out, you can use base_convert() for that.
As I said in the comment, keep in mind that this is not an efficient way to mask IDs. If you have a security problem when people can guess the next or previous ID to a record, this is very poor protection.
dechex will convert a number to hex for you. It won't obfuscate how many records are in a given system, however. I don't think it will make it any more efficient to store or save space, either.
You'd probably want to use a 2 way crypt function if obfuscation is needed. That won't save space, either.
Please state your goals more clearly and give more background, because this seems a bit pointless as it is.
This might confuse more people than simply converting the base of the numbers ...
Try using signed digits to represent your numbers. For example, instead of using digits 0..9 for decimal numbers, use digits -5..5. This Wikipedia article gives an example for the binary representation of numbers, but the approach can be used for any numeric base.
Using this together with, say, base-36 arithmetic might satisfy you.
EDIT: This answer is not really a solution to the question, so ignore it unless you are trying to hash a number.
My first thought we be to hash it using eg. md5 or sha1. (You'd probably not save any space though...)
To prevent people from using rainbow-tables or brute force to guess which number you hashed, you can always add a salt. It can be as simple as a string prepended to your number before hashing it.
md5 would return an alphanumeric string of exactly 32 chars and sha1 would return one of exaclty 40 chars.
Related
I'm trying to create an unique invoice id in PHP and currently doing this as following:
md5(time().$userId);
I may have concurrent users, so I'm adding user id as well to make sure it is unique, but the md5 hashing is 32 character long, is there any way to limit the output short (eg, 8-10 characters, if possible) while ensuring uniqueness?
NB: The output characters has to be same, therefore, just concating user id with time is not actually what I'm looking for since user id could be variable length, eg: 5, 20 or 100.
There are a few ways to ensure uniqunes
time() works fine for your purpose, since you're concatenating it with $userId.
You can use substr to take only parts of a string.
With that said, there are other ways to get unique strings in php
The one I find myself using more often than not is openssl_random_pseudo_bytes(). Notice the pseudo, it's not entirely random.
You can use it like this bin2hex(openssl_random_pseudo_bytes(2)), where 2 is the length of bytes, so it will equal to 4 characters.
You can also use urandom if you're on linux via exec OR even better, use fread
While it's better than the pseudo approach it's limited to the OS.
uniqid Also works fine.
If you really want something truly random, I suggest https://www.random.org/.
The randomness comes from atmospheric noise
They have an API you can use.
random_bytes (as suggested by #deceze) also works fine, do note that it's only available in PHP > 7
Pick your poison.
If i want to do this, use $userId.time()
I think this is unique because an user can't submit more than one order in a moment
Is there anything out there for PHP that can hash/encrypt a long string into a 128 bit string that can also be reversed?
I am trying importing hundreds on millions of strings into a MySQL DB and the average string is over 100 characters, MD5 gets this down to 32 characters which significantly reduces storage however I cannot reverse this again in my application.
Does PHP have anything available that can handle this?
If I understand your question correctly, it seems to me you mix up hashing and compression quite a lot.
Most hash-functions are not easily reversible, because that is not their purpose. There are infinite "Strings/ByteStreams/Numbers/..." that correspond to the result of a hash-function. As you may know, even images that are a few Gigabytes big, also give you an md5sum of 32 characters.
You can not just magically map any String into a String of fixed length that is shorter, to just be able to magically pouff it back to its original String.
It may well be, that some hash-functions could very efficiently be used to reverse their process if you know that your target results have to have this and that property (in you case maybe character-length of 100-120), but I doubt it.
Or do I totally misunderstand and you just mean ASCII-Strings with the expression "128 bit string"?
No, you can't do this: Pigeonhole principle
This may end up being a trivial question - I know I'm going to need to do this soon for an app I'm working on, but haven't really worked on it myself yet - I'm really just floating it to see if there's an obvious method I'm missing.
Basically, what I need is to generate a sequence of numbers using a-z, A-Z, 0-9, except without vowels. There is a small chance I will need to make it unpredictable, so being able to generate out of order is a bonus.
I'm initially thinking for each new one to just work forward from the last no-vowel match until I find the next one (or generate random numbers until I get one I don't have already in the case of unpredictable values), but is there a better way? Perhaps a baseX number system obj that allows you to specify the allowable characters?
Using PHP/MySQL if it matters.
There's a function in an answer of mine here that can convert from any base to any other and which lets you customize the digit pool; it also works on arbitrary-sized input. You can generate a sequence in base 10 and convert to whatever you need.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
php short hash
I need to generate a short hash. The shortest possible from urls say under 6 characters.
I need them to be unique just for the same domain, so a hash from
www.example.com/category/sth/blablabla must be different than one from
www.example.com/category2/sth/blabla but not from:
www.example2.com/category/sth/blablabla
Would using md5($url) and then picking some 5 characters out of that result (for example the first, last, middle and 2 other characters) give and unique id?
Would this abbreviated hash be unique as well?
A hash is not unique by definition. It's mathematically impossible to get a unique hash for something longer than the hash, unless it does not vary fully, which is the case for URLs but you cannot exploit it generally. Alternatively, you could use a simple incrementing ID, but that won't allow you to recognize matching URLs.
Either use a really long hash (at least 10 characters, ideally using upper and lower case letters), or accept collisions and handle them appropriately. Which is how actual hash tables work.
For low probability of collisions you can use universal hashing techniques. For example, choose a prime number P. Then for each character of the URL choose a random in the interval [0, P). Compute the hash of the URL as SUM(a[i]*c[i]) mod P, where c[i] is a character in the original URL. Then take the string containing the digits of the obtained integer as the hash.
Read more in this paper: http://www.cs.cmu.edu/~avrim/451/lectures/lect0929.pdf.
Yes, a small change in a URL will change pretty much every character in a good hash. MD5 or SHA1 is probably fine for this. Hence, take the first X characters - and you won't get any improvement by choosing the last X characters, or the first/last/middle. They're all good!
Obviously the more characters you put in your partial hash, the less likely you are to get collisions.
I would try using crc32($url); it will give an integer usually 10-11 digits-long, could be a negative value, but still it will be shorter than 32 chars for md5.
The only problem is that crc32 is not 100% unique, but it's very unlikely that two different URLs will end up with the same checksum (but still there is a possibility).
I have two strings and I would like to mix the characters from each string into one bigger string, how can I do this in PHP? I can swap chars over but I want something more complicated since it could be guessed.
And please don't say md5() is enough and irreversible. :)
$string1 = '9cb5jplgvsiedji9mi9o6a8qq1';//session_id()
$string2 = '5d41402abc4b2a76b9719d911017c592';//md5()
Thank you for any help.
EDIT: Ah sorry Rob. It would be great if there is a solution where it was just a function I could pass two strings to, and it returned a string.
The returned string must contain both of the previous strings. Not just a concatination, but the characters of each string are mingled into one bigger one.
If you want to make a tamper-proof string which is human readable, add a secure hash to it. MD5 is indeed falling out of favour, so try sha1. For example
$salt="secret";
$hash=sha1($string1.$string2.$salt);
$separator="_";
$str=$string1.$separator.$string2.$separator.$hash;
If you want a string which cannot be read by humans, encrypt it - check out the mcrypt extension which offers a variety of options.
Use one of the SHA variants of the hash() function. Sha2 or sha256 should be sufficient and certainly much better than anything you could come up with.
Unless I am missing something if your wanting to combine those values into a unique value why not do sha1(string1, string2);
I'm guessing you want something reversible, so you can get these values back out. A quick-and-dirty technique for obscuring these two strings further would be to base64-encode them:
base64_encode($string1 . $string2);
Thank you everyone. I completely forgot about the SHA1 - got too into solving a problem that I forgot what else was out there. :)
Well, if not md5(), then sha1(). :)
Anyway,the possibilities to mangle are endless, pick your poison.
What I would do, if I really wanted to do something like that (which can be useful occasionally), I would add another element, chosen on random and shuffle the md5 string by it. and write down the random element in it, too.
For example, let us add to each md5 character a random 2 digit number, which we then split by digits and add 1st digit to resulting string, and 2nd digit - prepend to it.
I stumbled upon someplace where something of that kind was done today. I was trying to find some reference to a particular phone number - whether it appears anywhere on the country-local inet or not.
I visited a popular classified ads site, which gives phone numbers of advertisers and you have the option, when you are looking at a particular ad, to find all ads with the same phone number. Now, what they did, however, was that they encoded search string, so you are not searching for ?phone=123123, but something like ?phone==FFYx23=.
If they hadn't done that, I would be able to find out for my own purposes, rather than checking on ads, IF user with phone 123123 has posted any ads on the site.
If you are looking to verify message integrity and authenticity with hashing - you might want to look at HMAC - there are plenty of implementations in PHP using both SHA1 and MD5:
http://en.wikipedia.org/wiki/HMAC
EDIT: In fact, PHP now has a function for this:
http://us3.php.net/manual/en/function.hash-hmac.php