Hexadecimal to base64 function?

is there a pre made way to go from a hexadecimal string (a string containing an arbitrary amount of hex data) to the base 64 representation of it? (base64_encode() is no good – it’s not aware of the fact that the passed to it string is hex therefore the base 64 version ends up longer, not shorter as it should be)

thanks.

Hm, not my forte, but what about…


function hex_to_base64($hex){
  $return = '';
  foreach(str_split($hex, 2) as $pair){
    $return .= chr(hexdec($pair));
  }
  return base64_encode($return);
}

Do you have a desired ‘before & after’ we can look at?

> Do you have a desired ‘before & after’

i don’t exactly, apart from the input are likely to be output from the md5 function, so 32 hex digits/characters. e.g. 14f45c3234cde9c27e81deabc6c6adbe

the logarithm (which is the opposite/reverse of, to the power of) of 16^32 (which is the number of unique values 32 hex digit strings have), base 64, is 21.333333… so that means the output of a hex to base64 function whose input is a 32 character long hex string should be 22 base 64 digits long.

having just given your function a quick test using the above example hex string as input, it outputs FPRcMjTN6cJ+gd6rxsatvg== which is 24 characters. those two ='s on the end may not be needed which would leave 22 characters, so it looks looks good on the face of it. thanks.

The base64 version will always be 1/3 longer than whatever you feed it. That’s what base64 does - it reduces the number of available bits per byte from 8 to 6 and then makes sure that the other two always contain a one and a zero so as to keep the frequency of the signal when converted from digital to analog within the supported frequency range of the phone line. There isn’t any other reason to use base64 unless you are going to use a modem to convert it to analog to send it through a phone line and so need to make sure that at least one bit is on and one off in every byte.

Anyway a single byte can contain 256 different values (from hex 00 to hex ff) whereas once it is base 64 encoded the byte can only contain 64 different values (from hex 00 to hex 3f) so why would you expect base64 encoding it and reducing the number of values a byte can store to 1/4.

If you are storing single hex digits in each byte then simply combine two of them into the one byte before base64 encoding it in order to get the shorter value - or since it placing a displayable hex character in each byte is plain text to start with you don’t need to base64 encode it at all as all plain text characters already fall within that range.

While there is bin2hex() function, there is no hex2bin(). You have to use pack() instead:

base64_encode(pack('H*',$hexadecimal_string));
  • md5() and sha() as well has option to output binary instead of hexadecimal.

> The base64 version will always be 1/3 longer than whatever you feed it.

when going from ascii to base64 (which is what php’s base64_encode() function is fixed to use as input) the output will be longer, and that’s what base64 is so commonly used for (to the point where base64 means ascii<->base64). ascii has an alphabet size of 128, base 64, an alphabet size of 64. because 128 is larger than 64, going from ascii to base 64 will yield longer output than the input.

even though base 64 is so often used to encode ascii, i’m not. ascii has nothing to do with what i’m doing (apart from i’m using ascii text to represent the hex data initially, and base 64 data can nicely be represented in ascii). i’m simply going from a base 16 encoding to a base 64 encoding – and the alphabet of the base 64 encoding i’m going to is the same alphabet as base64 when used to encode ascii.

have a look at AnthonySterling’s function. he’s got it right (although not tested fully but confirmed basically). this is absolutely correct as well:

the logarithm (which is the opposite/reverse of, to the power of) of 16^32 (which is the number of unique values 32 hex digit strings have), base 64, is 21.333333… so that means the output of a hex to base64 function whose input is a 32 character long hex string should be 22 base 64 digits long.

have a look at this, which i just found:
http://home1.paulschou.net/tools/xlate/
copy and paste the example hex data 14f45c3234cde9c27e81deabc6c6adbe into the hex box, click decode, and observe the data in the base64 box. it’s the same as the output from AnthonySterling’s function. without the ='s on the end (padding) it’s 22 characters long.

I think you’ll find that my code outputs the same result, as well:
http://codepad.org/7MREgnKF
:wink:

<?php
echo base64_encode(pack('H*','14f45c3234cde9c27e81deabc6c6adbe'));
?>

oh right, yup, sorry i hadn’t checked that. great, that’s pretty to the point. i had looked at that pack function to help with this but wasn’t sure what to do with it. great, thanks for pointing your solution out to me again.

Very nice, clear, succinct. I love it. :slight_smile:

> Very nice, clear, succinct. I love it.

agreed.