MD5-hash in Base32
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
$file = '/pad/naar/een/cachebestand.tmp';
$etag = md5_file($file);
$etag = base_convert($etag, 16, 32);
// $etag == string(26) "4sfh0pbocb8000000000000000"
$etag = md5_file($file);
$etag = hexdec($etag);
$etag = base_convert($etag, 10, 32);
// $etag == string(11) "1r3pb3t0r0a"
?>
$file = '/pad/naar/een/cachebestand.tmp';
$etag = md5_file($file);
$etag = base_convert($etag, 16, 32);
// $etag == string(26) "4sfh0pbocb8000000000000000"
$etag = md5_file($file);
$etag = hexdec($etag);
$etag = base_convert($etag, 10, 32);
// $etag == string(11) "1r3pb3t0r0a"
?>
Hoe kan ik de conversie uitvoeren met behoud van de volledige precisie?
string base_convert ( string $number , int $frombase , int $tobase )
In jou voorbeeld ga je van 16 naar 32 en daarna van 32 naar 10. Dat levert een verschil op
Laten hier op php.net nu op beide plekken in de user comments twee functies voor staan (respectievelijk str_baseconvert en bchexdec):
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
function str_baseconvert($str, $frombase=10, $tobase=36) {
$str = trim($str);
if (intval($frombase) != 10) {
$len = strlen($str);
$q = 0;
for ($i=0; $i<$len; $i++) {
$r = base_convert($str[$i], $frombase, 10);
$q = bcadd(bcmul($q, $frombase), $r);
}
}
else $q = $str;
if (intval($tobase) != 10) {
$s = '';
while (bccomp($q, '0', 0) > 0) {
$r = intval(bcmod($q, $tobase));
$s = base_convert($r, 10, $tobase) . $s;
$q = bcdiv($q, $tobase, 0);
}
}
else $s = $q;
return $s;
}
function bchexdec($hex)
{
$len = strlen($hex);
$dec = 0; // initialisatie ontbrak nog :p
for ($i = 1; $i <= $len; $i++)
$dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
return $dec;
}
?>
function str_baseconvert($str, $frombase=10, $tobase=36) {
$str = trim($str);
if (intval($frombase) != 10) {
$len = strlen($str);
$q = 0;
for ($i=0; $i<$len; $i++) {
$r = base_convert($str[$i], $frombase, 10);
$q = bcadd(bcmul($q, $frombase), $r);
}
}
else $q = $str;
if (intval($tobase) != 10) {
$s = '';
while (bccomp($q, '0', 0) > 0) {
$r = intval(bcmod($q, $tobase));
$s = base_convert($r, 10, $tobase) . $s;
$q = bcdiv($q, $tobase, 0);
}
}
else $s = $q;
return $s;
}
function bchexdec($hex)
{
$len = strlen($hex);
$dec = 0; // initialisatie ontbrak nog :p
for ($i = 1; $i <= $len; $i++)
$dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
return $dec;
}
?>
Ik heb hier verder geen wiskundige of technische onderbouwing voor, maar met de volgende hash als invoer van een arbitrair bestand leidt dit via beide wegen tot hetzelfde antwoord:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
$hash = 'dc3a240b57f9c6f87694b28c3c512b42';
// manier #1
echo str_baseconvert($hash, 16, 32).'<hr />'; // 6s78i0mlvpors7d55ihgu52aq2
// manier #2
$test = bchexdec($hash);
echo $test.'<br />'; // 292732043355959189153777150500485016386
echo str_baseconvert($test, 10, 32); // 6s78i0mlvpors7d55ihgu52aq2
?>
$hash = 'dc3a240b57f9c6f87694b28c3c512b42';
// manier #1
echo str_baseconvert($hash, 16, 32).'<hr />'; // 6s78i0mlvpors7d55ihgu52aq2
// manier #2
$test = bchexdec($hash);
echo $test.'<br />'; // 292732043355959189153777150500485016386
echo str_baseconvert($test, 10, 32); // 6s78i0mlvpors7d55ihgu52aq2
?>
Ook weet ik niet of je hier iets aan hebt :p.
Ik zag met jullie input dat ik het even moest omdenken. Base16 (hex) en Base32 zijn slechts stringnotaties van binaire data. Voor het zusje Base64 geldt hetzelfde. Ik kan dus ook md5_file() met binaire output gebruiken en daarna base64_encode() gebruiken voor de conversie naar een string. En dat werkt: