HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

base32 implementation in PHP

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
implementationbase32php

Problem

I don't actually know much about how base32 (or base64) works, but I noticed that there was no official base32 implementation in PHP, so I figured I'd make one.

I Googled around a bit to figure out how it works, and found this page. Using the examples at the bottom, I hacked up this base32 class. GitHub project: https://github.com/NTICompass/PHP-Base32

```
type = $alphabet;
// Crockford's alphabet removes I,L,O, and U
$crockfordABC = range('A', 'Z');
unset($crockfordABC[8], $crockfordABC[11], $crockfordABC[14], $crockfordABC[20]);
$crockfordABC = array_values($crockfordABC);

$alphabets = array(
'rfc4648' => array_merge(range('A','Z'), range(2,7), array('=')),
'crockford' => array_merge(range(0,9), $crockfordABC, array('='))
);
$this->encode = $alphabets[$alphabet];
$this->decode = array_flip($this->encode);
// Add extra letters for Crockford's alphabet
if($alphabet === 'crockford'){
$this->decode['O'] = 0;
$this->decode['I'] = 1;
$this->decode['L'] = 1;
}
}

private function bin_chunk($binaryString, $bits){
$binaryString = chunk_split($binaryString, $bits, ' ');
if($this->endsWith($binaryString, ' ')){
$binaryString = substr($binaryString, 0, strlen($binaryString)-1);
}
return explode(' ', $binaryString);
}

// String Binary conversion
// Based off: http://psoug.org/snippet/PHP-Binary-to-Text-Text-to-Binary_380.htm

private function bin2str($binaryString){
// Make sure binary string is in 8-bit chunks
$binaryArray = $this->bin_chunk($binaryString, 8);
$string = '';
foreach($binaryArray as $bin){
// Pad each value to 8 bits
$bin = str_pad($bin, 8, 0, STR_PAD_RIGHT);
// Convert binary strings to ascii
$string .= chr(bindec($bin));
}
return $string;
}

Solution

Your constructor going through all the work to build both alphabets and then throwing one away seems odd. I'd probably have a Base32 base class, and have the two alphabets be subclasses.

Using the binary conversion does seem problematic. This is especially true since the numbers are already in binary inside the computer.

I can see a few different approaches:

Make an array of 5 bit numbers:

value = 0
bits_remaining = 0
while more data or bits_remaining:
     while bits_remaining  > 5:
          remove first five bits of value and place into array
     value = value << 8 + ord(next letter in data)


Hand code for each 8 byte case:

codes = array(
     (value[0] & 0xfd)) >> 3,
     (value[0] & 0x3) > 3,
     ...


Since (8 * 5) % 8 = 0 you can chunk your data into eight bit pieces and just hand code the neccesary bitflags to figure out which index should be fetched.

Use GMP

value = gmp_init(0)
 for( letter in data)
 {
      value = gmp_or( gmp_mult( value, gmp_pow(2, 8)), ord(letter))
 }
 gmp_strval(value, 32)


(Actually algorithm have not been thought through, but perhaps this might give you an idea of things to try)

Code Snippets

value = 0
bits_remaining = 0
while more data or bits_remaining:
     while bits_remaining  > 5:
          remove first five bits of value and place into array
     value = value << 8 + ord(next letter in data)
codes = array(
     (value[0] & 0xfd)) >> 3,
     (value[0] & 0x3) << 3 | value[1] & (0x7) >> 3,
     ...
value = gmp_init(0)
 for( letter in data)
 {
      value = gmp_or( gmp_mult( value, gmp_pow(2, 8)), ord(letter))
 }
 gmp_strval(value, 32)

Context

StackExchange Code Review Q#5236, answer score: 2

Revisions (0)

No revisions yet.