Skip to content

Commit

Permalink
Bump minimum to 7.2, update deps, use GitHub Actions (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
francislavoie authored Oct 13, 2020
1 parent 9acf122 commit 380b0f8
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 95 deletions.
56 changes: 56 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Test

on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
test:
name: PHP ${{ matrix.php-versions }} on ${{ matrix.operating-system }}
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest]
php-versions: ['7.2', '7.3', '7.4']
# TODO: When bacon/bacon-qr-code supports PHP 8:
# php-versions: ['7.2', '7.3', '7.4', '8.0']

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
with:
php-version: ${{ matrix.php-versions }}
coverage: pcov
tools: composer:v2
env:
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Get composer cache directory
id: composercache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Setup problem matchers
run: |
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install Composer dependencies
run: composer install --prefer-dist

- name: Test with phpunit
run: composer test
23 changes: 0 additions & 23 deletions .travis.yml

This file was deleted.

13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
Google Authenticator (TOTP)
===========================

[![Build Status](https://travis-ci.org/Vectorface/GoogleAuthenticator.png?branch=master)](https://travis-ci.org/Vectorface/GoogleAuthenticator)
![Build Status](https://github.com/Vectorface/GoogleAuthenticator/workflows/Test/badge.svg)

This is a fork of https://github.com/PHPGangsta/GoogleAuthenticator with the following changes:

- Uses https://github.com/endroid/qr-code to generate QR code data URIs
- No longer generates Google's Chart API to make QR code links
- Uses namespacing
- Augmented test coverage to 100%
- Bumped minimum PHP version to 5.6
- Bumped minimum PHP version to 7.2

Original License:
-----------------
Expand All @@ -36,21 +36,22 @@ See following example:

```php
<?php
require_once __DIR__ . 'vendor/autoload.php';
require_once 'vendor/autoload.php';

use Vectorface\GoogleAuthenticator;

$ga = new GoogleAuthenticator();
$secret = $ga->createSecret();
echo "Secret is: ".$secret."\n\n";
echo "Secret is: {$secret}\n\n";

$qrCodeUrl = $ga->getQRCodeUrl('Blog', $secret);
echo "PNG Data URI for the QR-Code: ".$qrCodeUrl."\n\n";
echo "PNG Data URI for the QR-Code: {$qrCodeUrl}\n\n";

$oneCode = $ga->getCode($secret);
echo "Checking Code '$oneCode' and Secret '$secret':\n";

$checkResult = $ga->verifyCode($secret, $oneCode, 2); // 2 = 2*30sec clock tolerance
// 2 = 2*30sec clock tolerance
$checkResult = $ga->verifyCode($secret, $oneCode, 2);
if ($checkResult) {
echo 'OK';
} else {
Expand Down
7 changes: 3 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "vectorface/googleauthenticator",
"description": "Google Authenticator 2-factor authentication",
"version": "1.0.0",
"type": "library",
"keywords": ["GoogleAuthenticator", "TOTP", "rfc6238"],
"license": ["BSD-2-Clause"],
Expand All @@ -24,11 +23,11 @@
"issues": "https://github.com/Vectorface/GoogleAuthenticator/issues"
},
"require": {
"php": ">=5.6",
"endroid/qr-code": "^2"
"php": ">=7.2",
"endroid/qr-code": "^3.9.3"
},
"require-dev": {
"phpunit/phpunit": "^5 || ^6"
"phpunit/phpunit": "^8"
},
"config": {
"sort-packages": true
Expand Down
30 changes: 15 additions & 15 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false" bootstrap="./vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="default">
<directory>./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-text" target="php://stdout"/>
<log type="coverage-html" target="build/coverage"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
<testsuites>
<testsuite name="default">
<directory>./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-text" target="php://stdout"/>
<log type="coverage-html" target="build/coverage"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
</phpunit>
37 changes: 16 additions & 21 deletions src/GoogleAuthenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class GoogleAuthenticator
* @return string
* @throws Exception
*/
public function createSecret($secretLength = 16)
public function createSecret(int $secretLength = 16) : string
{
$validChars = self::base32LookupTable();

Expand All @@ -40,11 +40,6 @@ public function createSecret($secretLength = 16)
$rnd = false;
if (function_exists('random_bytes')) {
$rnd = random_bytes($secretLength);
} elseif (function_exists('openssl_random_pseudo_bytes')) {
$rnd = openssl_random_pseudo_bytes($secretLength, $cryptoStrong);
if (!$cryptoStrong) {
$rnd = false;
}
}

if (!$rnd) {
Expand All @@ -68,7 +63,7 @@ public function createSecret($secretLength = 16)
* @return string
* @throws Exception
*/
public function getCode($secret, $timeSlice = null)
public function getCode(string $secret, int $timeSlice = null) : string
{
if ($timeSlice === null) {
$timeSlice = floor(time() / 30);
Expand Down Expand Up @@ -107,7 +102,7 @@ public function getCode($secret, $timeSlice = null)
* @return string
* @throws Exception on encoding error
*/
public function getQRCodeUrl($name, $secret)
public function getQRCodeUrl(string $name, string $secret) : string
{
$uri = "otpauth://totp/$name?secret=$secret";
return 'data:image/png;base64,' . base64_encode($this->getQRCodeSRC($uri));
Expand All @@ -119,12 +114,12 @@ public function getQRCodeUrl($name, $secret)
* @param string $uri to encode into a QRCode
* @return string binary data of the PNG of the QRCode
*/
protected function getQRCodeSRC($uri)
protected function getQRCodeSRC(string $uri) : string
{
$qr_code = new QrCode($uri);
$qr_code->setSize(260);
$qr_code->setMargin(10);
$qr_code->setErrorCorrectionLevel(ErrorCorrectionLevel::LOW);
$qr_code->setErrorCorrectionLevel(ErrorCorrectionLevel::LOW());
$qr_code->setForegroundColor(['r' => 0, 'g' => 0, 'b' => 0]);
$qr_code->setBackgroundColor(['r' => 255, 'g' => 255, 'b' => 255]);
$qr_code->setValidateResult(false);
Expand All @@ -140,7 +135,7 @@ protected function getQRCodeSRC($uri)
* @param int $discrepancy This is the allowed time drift in 30 second units (8 means 4 minutes before or after)
* @return bool
*/
public function verifyCode($secret, $code, $discrepancy = 1)
public function verifyCode(string $secret, string $code, int $discrepancy = 1) : bool
{
$currentTimeSlice = floor(time() / 30);

Expand All @@ -151,7 +146,7 @@ public function verifyCode($secret, $code, $discrepancy = 1)
for ($i = -$discrepancy; $i <= $discrepancy; $i++) {
try {
$calculatedCode = $this->getCode($secret, $currentTimeSlice + $i);
} catch (\Exception $e) {
} catch (Exception $e) {
return false;
}

Expand All @@ -169,7 +164,7 @@ public function verifyCode($secret, $code, $discrepancy = 1)
* @param int $length
* @return self
*/
public function setCodeLength($length)
public function setCodeLength(int $length) : self
{
$this->_codeLength = $length;
return $this;
Expand All @@ -179,9 +174,9 @@ public function setCodeLength($length)
* Helper class to decode base32
*
* @param string $secret
* @return bool|string
* @return string
*/
private static function base32Decode($secret)
private static function base32Decode(string $secret) : string
{
if (empty($secret)) {
return '';
Expand All @@ -193,13 +188,13 @@ private static function base32Decode($secret)
$paddingCharCount = substr_count($secret, $base32chars[32]);
$allowedValues = [6, 4, 3, 1, 0];
if (!in_array($paddingCharCount, $allowedValues)) {
return false;
return '';
}

for ($i = 0; $i < 4; $i++){
if ($paddingCharCount == $allowedValues[$i] &&
substr($secret, -($allowedValues[$i])) != str_repeat($base32chars[32], $allowedValues[$i])) {
return false;
return '';
}
}

Expand All @@ -208,13 +203,13 @@ private static function base32Decode($secret)
$binaryString = "";
for ($i = 0; $i < count($secret); $i = $i+8) {
if (!in_array($secret[$i], $base32chars)) {
return false;
return '';
}

$x = "";
for ($j = 0; $j < 8; $j++) {
$secretChar = isset($secret[$i + $j]) ? $secret[$i + $j] : 0;
$base = isset($base32charsFlipped[$secretChar]) ? $base32charsFlipped[$secretChar] : 0;
$secretChar = $secret[$i + $j] ?? 0;
$base = $base32charsFlipped[$secretChar] ?? 0;
$x .= str_pad(base_convert($base, 10, 2), 5, '0', STR_PAD_LEFT);
}
$eightBits = str_split($x, 8);
Expand All @@ -231,7 +226,7 @@ private static function base32Decode($secret)
*
* @return array
*/
private static function base32LookupTable()
private static function base32LookupTable() : array
{
return [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
Expand Down
Loading

0 comments on commit 380b0f8

Please sign in to comment.