PHP encoding problem: how to encode base64 encoded uint8 bytes to hex - php

My problem is that I was some time ago base64 encoding random bytes from openssl sha256 in C (as uint8_t), feeding them into a shell script and using the output.
What I can recreate from my data now is:
Content of file.txt:
uvjWEHTUk1LnzVZul9ynRpezWfKYN3bvlx103wxACxo
test#test:~# base64 -d file.txt | od -t x1
0000000 ba f8 d6 10 74 d4 93 52 e7 cd 56 6e 97 dc a7 46
0000020 97 b3 59 f2 98 37 76 ef 97 1d 74 df 0c 40 0b 1a
The output is the same as calling in PHP:
echo bin2hex(base64_decode("uvjWEHTUk1LnzVZul9ynRpezWfKYN3bvlx103wxACxo="));
baf8d61074d49352e7cd566e97dca74697b359f2983776ef971d74df0c400b1a
What I did all the time in shell and need to do now in PHP is the following:
Again, same content of file.txt:
uvjWEHTUk1LnzVZul9ynRpezWfKYN3bvlx103wxACxo
test#test:~# base64 -d file.txt | od -t x8
0000000 5293d47410d6f8ba 46a7dc976e56cde7
0000020 ef763798f259b397 1a0b400cdf741d97
My problem here: what is now the equal procedure in PHP (to od -t x8 in shell)?
I tried pack / unpack / bin2hex / ... and can't get the same result.
I'm trying to get a string with this content:
"5293d47410d6f8ba46a7dc976e56cde7ef763798f259b3971a0b400cdf741d97"
from a starting point of base64_decode("uvjWEHTUk1LnzVZul9ynRpezWfKYN3bvlx103wxACxo="). Any ideas?

If x8 is what you really need, which is 8 bytes, then the implementation would be as simple as
<?php
$str = 'uvjWEHTUk1LnzVZul9ynRpezWfKYN3bvlx103wxACxo';
$bin = base64_decode($str);
if (strlen($bin) % 8 !== 0) {
throw new \RuntimeException('data length should be divisible by 8');
}
$result = '';
for ($i = 0; $i < strlen($bin); $i += 8) {
for ($j = $i + 7; $j >= $i; --$j) {
$result .= bin2hex($bin[$j]);
}
}
echo $result;
It iterates over blocks of 8 bytes, then dumps them in reverse order each.
Ideone: https://ideone.com/hBanqi

Related

How to read a float from binary WebM file?

I'm trying to learn binary and create a simple WebM parser in PHP based on Matroska.
I read TimecodeScale, MuxingAppm WritingApp, etc. with unpack(format, data). My problem is when I reach Duration (0x4489) in Segment Information (0x1549a966) I must read a float and based on TimecodeScale convert it to seconds: 261.564s->00:04:21.564 and I don't know how.
This is a sample sequence:
`2A D7 B1 83 0F 42 40 4D 80 86 67 6F 6F 67 6C 65 57 41 86 67 6F 6F 67 6C 65 44 89 88 41 0F ED E0 00 00 00 00 16 54 AE 6B`
TimecodeScale := 2ad7b1 uint [ def:1000000; ]
MuxingApp := 4d80 string; ("google")
WritingApp := 5741 string; ("google")
Duration := 4489 float [ range:>0.0; ]
Tracks := 1654ae6b container [ card:*; ]{...}
I must read a float after (0x4489) and return 261.564s.
The duration is a double precision floating point value (64-bits) represented in the IEEE 754 format. If you want to see how the conversion is done check this.
The TimecodeScale is the timestamp scale in nanoseconds.
In php you can do:
$bin = hex2bin('410fede000000000');
$timecode_scale = 1e6;
// endianness
if (unpack('S', "\xff\x00")[1] === 0xff) {
$bytes = unpack('C8', $bin);
$bytes = array_reverse($bytes);
$bin = implode('', array_map('chr', $bytes));
}
$duration = unpack('d', $bin)[1];
$duration_s = $duration * $timecode_scale / 1e9;
echo "duration=${duration_s}s\n";
Result:
duration=261.564s

NodeJS Buffer Equivalent In PHP

NodeJS code:
const salt = new Buffer('GHlDHToiZA1ViUu+W+EXww==', 'base64');
Output like this:
<Buffer 18 79 43 1d 3a 22 64 0d 55 89 4b be 5b e1 17 c3>
I need the same output in PHP. Read somewhere about PHP's pack function but I don't know how to use it.
Seems that you are working with base64; in php you are right pack and unpack is your friends.
example
in Node
$ node
> Buffer('hello world').toString('base64')
aGVsbG8gd29sZA==
in PHP
$ php -a
php > echo base64_encode('hello world');
aGVsbG8gd29ybGQ=
But if you are only looking for the binary:
in Node
> Buffer('hello wold')
<Buffer 68 65 6c 6c 6f 20 77 6f 6c 64>
in PHP
php > print_r(unpack('H*', 'hello world'));
Array
(
[1] => 68656c6c6f20776f726c64
)
So in your instance you would first decode the base64 and then unpack it.
php > $raw = base64_decode('GHlDHToiZA1ViUu+W+EXww==');
php > print_r(unpack('H*', $raw));
Array
(
[1] => 1879431d3a22640d55894bbe5be117c3
)
Easy peasy ;)
I have the same problem, and i found solution using the packet: lcobucci/jwt.
Must to create a buffer by your key in base64, after create will be converting to binary for sign the jwt.
$configuration = Configuration::forSymmetricSigner(
// You may use any HMAC variations (256, 384, and 512)
new Sha256(),
// replace the value below with a key of your own!
InMemory::base64Encoded('your-base64-key')
// You may also override the JOSE encoder/decoder if needed by providing extra arguments here
);

What kind of hash/encryption is this? '0E0B020601'

I've been asked to design back-end in php for a web app having ASP front-end. So I can't really dig up those ASP files. I have the MySQL database - that's it! The programmer who made the front-end isn't responding.
How do I decode this? Or just this - "what's the name of this encryption method?"
It looks something like HEX though.
Another sample - 0E0800160E0330595D57
0 1 2 3 4 5 6 7 8 9
0E 0B 02 06 01
0E 08 00 16 0E 03 30 59 5D 57
UPDATE - When I change my password to "kachwa" (without quotes), it gets updated as 040E0C07180E in the database.
Each byte is xor'd with 0x6f.
PHP sample encryption:
function enc($pass)
{
$enc = '';
for ($i = 0; $i < strlen($pass); ++$i)
$enc .= sprintf("%02x", ord($pass[$i]) ^ 0x6f);
return $enc;
}
echo enc("kachwa"),"\n";
Output:
040e0c07180e
And for the sake of completeness:
function dec($pass)
{
$dec = '';
foreach (str_split($pass, 2) as $hex)
$dec .= chr(hexdec($hex) ^ 0x6f);
return $dec;
}
echo dec("040e0c07180e"),"\n";

Get Least Significant Bit in PHP from Hex

I have a file with hex code and I need to get all the least significant bits from every byte in the file, concatenate them, split them in groups of 8 and then convert the bytes into ASCII. My problem is to extract the LSB from every byte.
The hex file looks like this (but is much longer):
58 00 00 1F 58 00 00 00 00 00 00 00 00 00 00 1C 22 23 1F 26 25 1E 2C 26 20 31 2B 22 38 2F 26 42 36 25 47 37 24 49 39 22
My code looks like this:
<?php
// Read file, remove spaces
$file = implode('', explode(' ', file_get_contents('vogel.hex')));
// Save LSB
$bits = array();
for ($i = 1; $i < strlen($file); ++$i)
{
$bits[] = $file[$i] & 1;
}
// Split LSB array into chunks of 8 bits.
$bytes = array_chunk($bits, 8);
// Implode byte arrays, convert to decimal, convert to ASCII.
foreach ($bytes as $byte)
{
echo chr(bindec(implode('', $byte)));
}
?>
I think that the splitting and converting part should work correctly, but I think I made a mistake when extracting the LSB. Can someone provide an example how I can extract the LSB?
I slightly edited my code, so that I start reading the bits at position 1. Then the decimal representation is within the ASCII range and the script outputs an actual ASCII character.
You could simply build up the bit string within the for loop, skipping the entire array procedure:
$bits = '';
for ($i = 1; $i < strlen($file); $i++) {
$bits .= (($file[$i] & 1) == 0) ? '0' : '1';
if ($i % 8 == 0) {
echo bindec($bits);
$bits = '';
}
}
Of course, you'd have some dangling bits if the input file's size isn't a multiple of 8.
A lot of programmers might cringe at your solution, but it works just fine with both ASCII and EBCDIC. I don't know of any other character set one might possibly be using with PHP.
The least significant bit of the character digit is the same as the value it represents. So your code will work. But it really deserves to have a comment explaining it relies on the least significant bit of the ASCII/EBCDIC display codes being the same as the digit.
what about shifting the hex left for hexvalue/2 times?
$hex = 0x05;
$shiftVal = (0 + $hex)/2;
echo $hex>>$shiftVal;//should output 1
another approach is to convert the hex to a number and see if it's odd or even:
$hex = 0xad;
echo $hex%2;

PHP Problem reading the hex values between these addresses?

<?php
$file = 'file.dat';
$file_contents = file_get_contents($file);
for ($i = 0x000481; $i <= 0x00048B; $i++) {
print $i;
}
?>
I am creating an online file analyzer but I have a small problem. It outputs (which is the actual position the hex is in)
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
when it should be
44 72 48 79 64 72 61 6C 69 73 6B
which his hex for DrHydralisk (me). Can anyone help me output the latter or just have it strait output ASCII (but hex is fine, I can just convert it)?
edit
Here is an image of what I am trying to do that I think will help.
http://imgur.com/nwenA.png
Here is the file I am trying to read, its a Starcraft replay (file.SC2Replay). Just search for DrHydralisk in a hex editor and that is where I am trying to read from.
http://www.mediafire.com/?6w8wi35q3o6ix8q
It should be (if clear text is in the file):
for( $i=0x481; $i<0x48D; $i++ ) {
printf("%X ", ord($file_contents[$i]));
}
Note the loop boundaries: 0x481 .. 0x48D
Result:
44 72 20 48 79 64 72 61 6C 69 73 6B
If the file contains hexadecimal numbers, this would be impossible because you need two bytes per hex char for the ascii character value range. So what is really in the file?
Edit
After reading your file, i did:
...
$file = 'file.SC2Replay';
$file_contents = file_get_contents($file);
for( $i=0x438; $i<0x443; $i++) {
printf("%X ", ord($file_contents[$i]));
}
for( $i=0x438; $i<0x443; $i++) {
printf("%s ", $file_contents[$i]);
}
...
And it says:
72 48 79 64 72 61 6C 69 73 6B
and
D r H y d r a l i s k
You messed up the file position ;-)
Regards
rbo
EDIT:
Thanks for providing the file, helped a lot! Beleive I got it working too:
//Do binary safe file read
$filename = 'file.SC2Replay';
$file = fopen($filename, "rb");
$contents = fread($file, filesize($filename));
fclose($file);
//position 1080 - 1091
for ($i = 0x438; $i < 0x443; $i++)
echo $contents[$i];
The reasons you were probably having problems is that first of all, a binary safe file read in php automatically replaces the bytes with the correct ASCII characters, so that threw off what position you actually needed to start reading from. Intead of 1153, it starts at 1080.
Could you explain how you are using the file you read in? Because the hex equivalent of:
11531154115511561157115811591160116111621163
is:
481 482 483 484 485 486 487 488 489 48a 48b
Also, there are two php functions you may find helpful
chr(int): returns the ascii character associated with the integer provided - http://php.net/manual/en/function.chr.php
dechex(int): returns the hex value of the integer provided - http://php.net/manual/en/function.dechex.php

Categories