BIN2HEX & HEX2BIN Convesion in PHP - php

I want to convert 48 bit binary number (in string format) to HEX (12 char long). And same thing in reverse manner.
E.g
binary '000000000000000000000000000000000000000000000000' into hex '00000000000'
binary '111111111111111111111111111111111111111111111111' into hex 'FFFFFFFFFFFF'
hex 'FFFFFFFFFFFF' into binary '111111111111111111111111111111111111111111111111'
hex '00000000000' into binary '000000000000000000000000000000000000000000000000'
Tried the default bin2hex(), dechex(bindec($binary)), etc.
I am a newbie so please explain in detail.

dechex(bindec($binary)) should have worked ok, but you don't say what the problem was.
Fundamentally though, the hex2bin is for encoding binary data, not a binary string. For simplicity's sake, you might want to stick to using the in-built base_convert function, e.g.
echo base_convert('FFFFFFFFFFFF', 16, 2);
// 111111111111111111111111111111111111111111111111
echo base_convert('111111111111111111111111111111111111111111111111', 2, 16);
// ffffffffffff
Note that for your "zero" examples, you'll just get back a single zero. There's no real concept of length with the number zero in any base system that I'm aware of.

Related

Is there way to know data is decimal or binary or hexadecimal?

I need to convert data of which I don't know whether it is
decimal
binary
hexadecimal
to decimal format.
So far, I have tried to use
bindec() to convert binary data to decimal
hexdec() to convert a hexadecimal to decimal
However, I need to determine beforehand whether a number is decimal or hexadecimal.
Is there a way to do that?
The only disctinction between arbitrary bases you can encounter are literals. In PHP, every number are stored as integers or floats.
$binary = 0b1100; // stored as 12
$oct = 014; // stored as 12
$hex = 0xC; // stored as 12
However, if your data is a string, you can use regex to determine it's type, than use hexdec(), octdec(), bindec() functions to convert them to decimal.
OR, you can use the intval() function, which automatically detects the type by the formatting of the string:
intval("0b000"); // bin->dec conversion
intval("014"); // oct->dec conversion
intval("0xC"); // hex->dec conversion
intval("12"); // str->dec cast!!
intval("asd"); // str->dec cast!!
Watch out with unformatted strings, because intval() will turn everything into a number.

PHP Function hex2bin() doesn't return binary strings

The php manual says that hex2bin() returns a string with a binary representation.
I have this code:
$hex = hex2bin("6578616d706c65206865782064617461");
var_dump($hex);
The output is:
string 'example hex data' (length=16)
Pardon me if I'm wrong but I believe that the output isn't a binary string??
Did the manual made an error, or am I missing something?
-------------edit------------
Is 'example hex data' a binary representation of data?
hex2bin turns hexadecimal numbers into raw bytes. These raw bytes output to the screen will be interpreted by your browser and/or CLI, which will turn it into text. bin2hex does not return a string like "01001000101" if that's what you expected; that'd be an ASCII representation of a binary string, not a binary string. See for example this if that's what you want: How to see binary representation of variable
From php manual:
"This function does NOT convert a hexadecimal number to a binary number. This can be done using the base_convert() function."
"Decodes a hexadecimally encoded (binary) string" and "Returns the binary representation of the given data"
(machine code ie. what's written to disk or processed by the computer hardware)
To answer your question:
Yes 'example hex data' is a (decoded) binary representation of (the given text) data.
The hex (encoded) representation of the same data is 6578616d706c65206865782064617461.
To display the binary (base 2) equivalent of the above hex (base 16) number, you'd base_convert() it (to get a string of 0s & 1s; the ASCII codes/representation)
The confusion seems to arise between the results of hex2bin and base_convert().
As an example:
Some data on disk can be displayed (on console) as 'A' bin2hex
would return this (encoded) as '41' (hex representation).
base_convert() would return this (same) data as '01000001'
hex2bin would then decode this '41' to the machine (ASCII)
code equivalent 'A' (the binary representation, which may be written to disk as binary data)

Most space efficient encoding that generate printable string in PHP?

I have a large string $string that when applied to md5(), give me
c4ca4238a0b923820dcc509a6f75849b
The length is 32, I want to reduce it, so
base64_encode(md5($string, true));
xMpCOKC5I4INzFCab3WEmw==
Removing the last two == it give me a string with length = 22.
Are there any other better algorithms?
I am not sure you realised that md5 is a hash function, and therefore irreversible. If you do not care about reversibility, you could just as well trim the md5 hash (or any hash of your liking*) down to an arbitrary number of characters. All this would do is increase the likelihood of collision (I feel this does not produce an uniform distribution though).
If you are looking for a reversible (ie. non-destructive) compression, then do not reinvent the wheel. Use the built-in functions, such as gzdeflate() or gzcompress(), or other similar functions.
*Here is a list of hash functions (wikipedia) along with the size of their output.
I suppose the smallest possible "hash function" would be a parity bit :)
One better way would be to, instead of converting to binary to hexadecimal (as md5 does) and then converting the string to base64, instead convert from the hexadecimal md5 directly to base64.
Since hexadecimal is 16 bits per character, and base64 is 64 bits per character, every 2 hexadecimal characters will make up one base64 character.
To perform the conversion, you can do the following:
Split the string into sixteen 2 character chunks
The first character should be multiplied by 2 and added to the second (keeping in mind that A-F = 10-15).
This number can be matched to the base64 scheme using the table from here: https://en.wikipedia.org/wiki/Base64
This will result in a 16 character base64 string with the same value as the hexadecimal representation of the md5 string.
Theoretically, you could do the same for any base. If we had a way to encode base128 strings in ASCII, we could end up with an 8 character string. However, as the character set is limited, I think base64 is the highest base that is commonly used.
The smaller the length of the string you want .. the smaller the number of possible combination
Total Number of Possibility with reputation
Total Possibility = nr
Since we are dealing with base64 has the printable output this means we only have 64 characters
n = 64
If you are looking at 22 letters in length
nr = 6422 = 5,444,517,870,735,015,415,413,993,718,908,291,383,296 possibilities
Back to your question : Are there any better algorithm?
Truncate the string with a good hash to desired length you want since the total possibility and collision is fixed
$string = "the fox jumps over the lazy brown dog";
echo truncateHash($string, 8);
Output
9TWbFjOl
Function Used
function truncateHash($str, $length) {
$hash = hash("sha256", $str, true);
return substr(base64_encode($hash), 0, $length);
}
This encoding generates shorter string,
print base64_encode(hash("crc32b",$string,1));
output
qfQIdw==
Not sure if MD5 is the right choice for you, but i will assume that you have reason to stick with this algorithm and are looking for a shorter representation. There are several possibilities to generate a shorter string with different alphabets:
Option 1: Binary string
The shortest possbile form of an MD5 is it's binary representation, to get such a string you can simply call:
$binaryMd5 = md5($input, true);
This string you can store like any other string in a database, it needs only 16 characters. Just make sure you do a proper escaping, either with mysqli_real_escape_string() or with parametrized queries (PDO).
Option 2: Base64 encoding
Base64 encoding will produce a string with this alphabet: [0-9 A-Z a-z + /] and uses '=' as padding. This encoding is very fast, but includes the sometimes unwanted characters '+/='.
$base64Md5 = base64_encode(md5($input, true));
The output length will be always 24 characters for the MD5 hash.
Option 3: Base62 encoding
The base62 encoding only uses the alphabet [0-9 A-Z a-z]. Such strings can be safely used for any purpose like tokens in an URL, and they are very compact. I wrote a base62 encoder, which is able to convert binary strings to the base62 alphabet. It may not be the fastest possible implementation, but it was my goal to write understandable code. The same class could be easily adapted to different alphabets.
$base62Md5 = StoBase62Encoder::base62encode(md5($input, true));
The output length will vary from 16 to 22 characters for the MD5 hash.
Base 91 looks like the most space efficient binary to ASCII printable encoding algorithm (which is what it seems you want).
I've not seen the PHP implementation, but if your software has to work with others I'd stick to Base 64; it's well-known, lightning fast, and available everywhere.
Firstly, to answer your question: Yes, there is a better algorithm (if with "better" you mean "shorter").
Use the hash() function (which has been part of the PHP core and enabled by default since PHP 5.1.2.) with any of the adler32, fnv132, crc32, crc32b, fnv132 or joaat algorithms.
Without a more in-depth knowledge of your current situation, you might as well just pick whichever one you think sounds the coolest.
Here is an example:
hash('crc32b', $string)
I set up an online example you can play around with.
Secondly, I would like to point out that what you are asking is an almost exact duplicate of another question here on stackoverflow.
I read from your post that you are searching for a hashing algorithm and not compression.
There are various standard hashing algorithms in php out there. Have a look at PHP hashing functions.
Depending on what you want to hash there are different approches. Be careful and calculate the average collision probability.
However it seems you are searching for a 'compression' which outputs the minimum possible size of chars for a given string. If you do, then have a look at Lempel–Ziv–Welch (php implementation) or others.

Check for binary string length?

Is there a native or inexpensive way to check for the length of a string in bytes in PHP?
See http://bytes.com/topic/php/answers/653733-binary-string-length
Relevant part:
"In PHP, like in C, the string ends with a zero-character, '\0', (char)
0, null-terminator, null-byte or whatever you like to call it."
No, that's not the case - PHP strings are stored with both the length and the
data, unlike C strings that just has one pointer and uses a terminator. They're
"binary-safe" - NUL doesn't terminate the string.
See the definition of zvalue_value in zend.h; the string part has both a "char
*val" and "int len".
Problems would start if you're using the mbstring.func_overload, which changes
how strlen() and the other functions work, and does try and treat strings as
strings of characters in a specific encoding rather than a string of bytes.
This is not the normal PHP behaviour.
The answer is that strlen should return the number of bytes regardless of the content of the string. For multi-byte character strings, you get the wrong number of characters, but the right number of bytes. However, you need to be certain you're not using the mbstring overload, which changes how strlen behaves.
In the event that you have mbstring overload set or your are developing for the platforms where you are unsure about this setting you can do the following:
$len=strlen(bin2hex($data))/2;
The reason why this works is that in Hex you are guaranteed to get 2 characters for all bytes that come from bin2hex (it returns two chars even for the initial binary 0).
Note that it will use significantly more resources than a normal strlen (afterall, so you should definitely not do that to the large amount of data if it's not absolutely necessary.
On php.org, someone was nice enough to create this function. Just multiply by 8 and you've got however many bits were in that string, as the function returns bytes.
The length of a string (textual data) is determined by the position of the NULL character which marks the end.
In case of binary data, NULL can be and often is in the middle of data.
You don't check the length of binary data. You have to know it beforehand. In your case, the length is 16 (bytes, not bits, if it is UUID).
As far as UUID validity is concerned, any 16-byte value is a valid UUID, so you are out of luck there.

PHP: Very simple Encode/Decode string

Is there any PHP function that encodes a string to a int value, which later I can decode it back to a string without any key?
Sure, you can convert strings to numbers and vice versa. Consider:
$a = "" + 1
gettype($a) // integer
$b = "$a"
gettype($b) // string
You can also do type casting with settype().
If I misunderstood you and you want to encode arbitrary strings, consider using base64_encode() and bas64_decode(). If you want to convert the base 64 string representation to a base 10 integer, simply use base_convert().
And int has 4 or 8 bytes depending on the platform, and each character in a string is one byte (or more depending on encoding). So, you can only encode very small strings to integers, which basically makes the answer to your question: no.
What do you want to accomplish?
I would suspect not, since there are far more possible string combinations than integers within the MAX_INT.
Does it have to be an integer?
i'm convinced that what you think you want to do is not really what you want to do. :-) this just sounds like a silly idea. As another user has asked before:) what do you need this for? What are your intentions?
Well now that you mentioned that numbers and a-z letter are acceptable, then I have one suggestion, you could loop through the individual letters' ordinal value and display that as a two-digit hexadecimal. You can then convert these hexadecimals back to the ordinal values of the individual characters. Don't know what kind of characters are you about to encode, possibly you will need to use 4-characters per letter (e.g. String Peter would become 00700065007400650072 ) Well... have fun with that, I still don't really see the rationale for doing what you're doing.
op through the individual letters' ordinal value and display that as a two-digit hexadecimal. You can then convert these hexadecimals back to the ordinal values of the individual characters. Don't know what kind of characters are you about to encode, possibly you will need to use 4-characters per letter (e.g. String Peter would become 00700065007400650072 ) Well... have fun with that, I still don't really see the
There is no function for PHP but I recently wrote a class to encrypt and decrypt a string in PHP. You can look at it at: https://github.com/Lars-/PHP-Security-class

Categories