Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: php

php:
- 5.3
- 5.4

script: phpunit --coverage-text
31 changes: 31 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "google/authenticator",
"description": "Library to integrate Google Authenticator into a PHP project",
"keywords": ["google authenticator"],
"homepage": "https://github.com/rande/GoogleAuthenticator.php",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Thomas Rabaix",
"email": "thomas.rabaix@gmail.com"
},
{
"name": "Christian Stocker",
"email": "me@chregu.tv"
},
{
"name": "Andre DeMarre",
"homepage": "http://www.devnetwork.net/viewtopic.php?f=50&t=94989"
}

],
"require": {
"php": ">=5.3.0"
},
"autoload": {
"psr-0": {
"Exporter": "lib/"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<?php

namespace Google\Authenticator;

/**
* FixedBitNotation
*
* @author Andre DeMarre
* @package FixedBitNotation
*/

/**
*
* The FixedBitNotation class is for binary to text conversion. It
* can handle many encoding schemes, formally defined or not, that
* use a fixed number of bits to encode each character.
Expand All @@ -23,7 +23,7 @@ class FixedBitNotation
protected $_padFinalGroup;
protected $_padCharacter;
protected $_charmap;

/**
* Constructor
*
Expand All @@ -35,52 +35,49 @@ class FixedBitNotation
* output
* @param string $padCharacter Character to use for padding
*/
public function __construct(
$bitsPerCharacter, $chars = NULL, $rightPadFinalBits = FALSE,
$padFinalGroup = FALSE, $padCharacter = '=')
public function __construct($bitsPerCharacter, $chars = NULL, $rightPadFinalBits = FALSE, $padFinalGroup = FALSE, $padCharacter = '=')
{
// Ensure validity of $chars
if (!is_string($chars) || ($charLength = strlen($chars)) < 2) {
$chars =
$chars =
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,';
$charLength = 64;
}

// Ensure validity of $bitsPerCharacter
if ($bitsPerCharacter < 1) {
// $bitsPerCharacter must be at least 1
$bitsPerCharacter = 1;
$radix = 2;

} elseif ($charLength < 1 << $bitsPerCharacter) {
// Character length of $chars is too small for $bitsPerCharacter
// Set $bitsPerCharacter to greatest acceptable value
$bitsPerCharacter = 1;
$radix = 2;

while ($charLength >= ($radix <<= 1) && $bitsPerCharacter < 8) {
$bitsPerCharacter++;
}

$radix >>= 1;

} elseif ($bitsPerCharacter > 8) {
// $bitsPerCharacter must not be greater than 8
$bitsPerCharacter = 8;
$radix = 256;

} else {
$radix = 1 << $bitsPerCharacter;
}

$this->_chars = $chars;
$this->_bitsPerCharacter = $bitsPerCharacter;
$this->_radix = $radix;
$this->_rightPadFinalBits = $rightPadFinalBits;
$this->_padFinalGroup = $padFinalGroup;
$this->_padCharacter = $padCharacter[0];
}

/**
* Encode a string
*
Expand All @@ -92,21 +89,21 @@ public function encode($rawString)
// Unpack string into an array of bytes
$bytes = unpack('C*', $rawString);
$byteCount = count($bytes);

$encodedString = '';
$byte = array_shift($bytes);
$bitsRead = 0;

$chars = $this->_chars;
$bitsPerCharacter = $this->_bitsPerCharacter;
$rightPadFinalBits = $this->_rightPadFinalBits;
$padFinalGroup = $this->_padFinalGroup;
$padCharacter = $this->_padCharacter;
// Generate encoded output;

// Generate encoded output;
// each loop produces one encoded character
for ($c = 0; $c < $byteCount * 8 / $bitsPerCharacter; $c++) {

// Get the bits needed for this encoded character
if ($bitsRead + $bitsPerCharacter > 8) {
// Not enough bits remain in this byte for the current
Expand All @@ -115,52 +112,52 @@ public function encode($rawString)
$oldBitCount = 8 - $bitsRead;
$oldBits = $byte ^ ($byte >> $oldBitCount << $oldBitCount);
$newBitCount = $bitsPerCharacter - $oldBitCount;

if (!$bytes) {
// Last bits; match final character and exit loop
if ($rightPadFinalBits) $oldBits <<= $newBitCount;
$encodedString .= $chars[$oldBits];

if ($padFinalGroup) {
// Array of the lowest common multiples of
// Array of the lowest common multiples of
// $bitsPerCharacter and 8, divided by 8
$lcmMap = array(1 => 1, 2 => 1, 3 => 3, 4 => 1,
5 => 5, 6 => 3, 7 => 7, 8 => 1);
$bytesPerGroup = $lcmMap[$bitsPerCharacter];
$pads = $bytesPerGroup * 8 / $bitsPerCharacter
$pads = $bytesPerGroup * 8 / $bitsPerCharacter
- ceil((strlen($rawString) % $bytesPerGroup)
* 8 / $bitsPerCharacter);
$encodedString .= str_repeat($padCharacter[0], $pads);
}

break;
}

// Get next byte
$byte = array_shift($bytes);
$bitsRead = 0;

} else {
$oldBitCount = 0;
$newBitCount = $bitsPerCharacter;
}

// Read only the needed bits from this byte
$bits = $byte >> 8 - ($bitsRead + ($newBitCount));
$bits ^= $bits >> $newBitCount << $newBitCount;
$bitsRead += $newBitCount;

if ($oldBitCount) {
// Bits come from seperate bytes, add $oldBits to $bits
$bits = ($oldBits << $newBitCount) | $bits;
}

$encodedString .= $chars[$bits];
}

return $encodedString;
}

/**
* Decode a string
*
Expand All @@ -170,107 +167,106 @@ public function encode($rawString)
* an undecodable character
* @return string|NULL
*/
public function decode($encodedString, $caseSensitive = TRUE,
$strict = FALSE)
public function decode($encodedString, $caseSensitive = TRUE, $strict = FALSE)
{
if (!$encodedString || !is_string($encodedString)) {
// Empty string, nothing to decode
return '';
}

$chars = $this->_chars;
$bitsPerCharacter = $this->_bitsPerCharacter;
$radix = $this->_radix;
$rightPadFinalBits = $this->_rightPadFinalBits;
$padFinalGroup = $this->_padFinalGroup;
$padCharacter = $this->_padCharacter;

// Get index of encoded characters
if ($this->_charmap) {
$charmap = $this->_charmap;

} else {
$charmap = array();

for ($i = 0; $i < $radix; $i++) {
$charmap[$chars[$i]] = $i;
}

$this->_charmap = $charmap;
}

// The last encoded character is $encodedString[$lastNotatedIndex]
$lastNotatedIndex = strlen($encodedString) - 1;

// Remove trailing padding characters
while ($encodedString[$lastNotatedIndex] == $padCharacter[0]) {
$encodedString = substr($encodedString, 0, $lastNotatedIndex);
$lastNotatedIndex--;
}

$rawString = '';
$byte = 0;
$bitsWritten = 0;

// Convert each encoded character to a series of unencoded bits
for ($c = 0; $c <= $lastNotatedIndex; $c++) {

if (!isset($charmap[$encodedString[$c]]) && !$caseSensitive) {
// Encoded character was not found; try other case
if (isset($charmap[$cUpper
if (isset($charmap[$cUpper
= strtoupper($encodedString[$c])])) {
$charmap[$encodedString[$c]] = $charmap[$cUpper];
} elseif (isset($charmap[$cLower

} elseif (isset($charmap[$cLower
= strtolower($encodedString[$c])])) {
$charmap[$encodedString[$c]] = $charmap[$cLower];
}
}

if (isset($charmap[$encodedString[$c]])) {
$bitsNeeded = 8 - $bitsWritten;
$unusedBitCount = $bitsPerCharacter - $bitsNeeded;

// Get the new bits ready
if ($bitsNeeded > $bitsPerCharacter) {
// New bits aren't enough to complete a byte; shift them
// New bits aren't enough to complete a byte; shift them
// left into position
$newBits = $charmap[$encodedString[$c]] << $bitsNeeded
$newBits = $charmap[$encodedString[$c]] << $bitsNeeded
- $bitsPerCharacter;
$bitsWritten += $bitsPerCharacter;

} elseif ($c != $lastNotatedIndex || $rightPadFinalBits) {
// Zero or more too many bits to complete a byte;
// Zero or more too many bits to complete a byte;
// shift right
$newBits = $charmap[$encodedString[$c]] >> $unusedBitCount;
$bitsWritten = 8; //$bitsWritten += $bitsNeeded;

} else {
// Final bits don't need to be shifted
$newBits = $charmap[$encodedString[$c]];
$bitsWritten = 8;
}

$byte |= $newBits;

if ($bitsWritten == 8 || $c == $lastNotatedIndex) {
// Byte is ready to be written
$rawString .= pack('C', $byte);

if ($c != $lastNotatedIndex) {
// Start the next byte
$bitsWritten = $unusedBitCount;
$byte = ($charmap[$encodedString[$c]]
$byte = ($charmap[$encodedString[$c]]
^ ($newBits << $unusedBitCount)) << 8 - $bitsWritten;
}
}

} elseif ($strict) {
// Unable to decode character; abort
return NULL;
}
}

return $rawString;
}
}
Loading