MD5-hash in Base32

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ward van der Put
Moderator

Ward van der Put

03/06/2016 14:58:32
Quote Anchor link
Voor een ETag wil ik een hexadecimale MD5-hash converteren naar Base32. Dat heb ik op de volgende twee manieren geprobeerd, maar ik krijg door afrondingsverschillen onnauwkeurige resultaten:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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"
?>


Hoe kan ik de conversie uitvoeren met behoud van de volledige precisie?
 
PHP hulp

PHP hulp

06/05/2021 23:41:50
 
TJVB tvb

TJVB tvb

03/06/2016 15:41:24
Quote Anchor link
Als ik in de handleiding kijk:
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
 
Thomas van den Heuvel

Thomas van den Heuvel

03/06/2016 17:01:20
Quote Anchor link
Hm, zowel base_convert alsmede hexdec lijken beide te kampen met afrondingen en conversies.

Laten hier op php.net nu op beide plekken in de user comments twee functies voor staan (respectievelijk str_baseconvert en bchexdec):
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?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;
}

?>

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)
PHP script in nieuw venster Selecteer het PHP script
1
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
?>

Ook weet ik niet of je hier iets aan hebt :p.
 
Ward van der Put
Moderator

Ward van der Put

03/06/2016 17:29:08
Quote Anchor link
Dank jullie wel!

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:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$etag
= md5_file($file, true);
$etag = base64_encode($etag);
?>
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.