mirror of
https://github.com/RobThree/TwoFactorAuth.git
synced 2026-08-25 16:56:35 +00:00
Merge branch 'master' into github_action
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [RobThree]
|
||||
custom: ["https://paypal.me/robiii"]
|
||||
+5
-2
@@ -125,7 +125,7 @@ publish/
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
@@ -184,6 +184,9 @@ FakesAssemblies/
|
||||
|
||||
# Composer
|
||||
/vendor
|
||||
composer.lock
|
||||
|
||||
# .vs
|
||||
.vs/
|
||||
.vs/
|
||||
|
||||
.phpunit.result.cache
|
||||
|
||||
+13
-4
@@ -21,11 +21,12 @@
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "@stable"
|
||||
"phpunit/phpunit": "@stable",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2"
|
||||
},
|
||||
"suggest": {
|
||||
"bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
|
||||
"endroid/qr-code": "Needed for EndroidQrCodeProvider"
|
||||
"bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
|
||||
"endroid/qr-code": "Needed for EndroidQrCodeProvider"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -34,7 +35,15 @@
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"RobThree\\Auth\\Test\\": "tests"
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"lint": [
|
||||
"parallel-lint --exclude vendor ."
|
||||
],
|
||||
"test": [
|
||||
"XDEBUG_MODE=coverage phpunit"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Generated
-980
@@ -1,980 +0,0 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "9647de85f54ba6db237f5ff42ff85a1f",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
"version": "1.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/instantiator.git",
|
||||
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
|
||||
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3,<8.0-DEV"
|
||||
},
|
||||
"require-dev": {
|
||||
"athletic/athletic": "~0.1.8",
|
||||
"ext-pdo": "*",
|
||||
"ext-phar": "*",
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"squizlabs/php_codesniffer": "~2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Marco Pivetta",
|
||||
"email": "ocramius@gmail.com",
|
||||
"homepage": "http://ocramius.github.com/"
|
||||
}
|
||||
],
|
||||
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
|
||||
"homepage": "https://github.com/doctrine/instantiator",
|
||||
"keywords": [
|
||||
"constructor",
|
||||
"instantiate"
|
||||
],
|
||||
"time": "2015-06-14T21:17:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-docblock",
|
||||
"version": "2.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
||||
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
|
||||
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"dflydev/markdown": "~1.0",
|
||||
"erusev/parsedown": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"phpDocumentor": [
|
||||
"src/"
|
||||
]
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mike van Riel",
|
||||
"email": "mike.vanriel@naenius.com"
|
||||
}
|
||||
],
|
||||
"time": "2015-02-03T12:10:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "v1.6.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy.git",
|
||||
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb",
|
||||
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/instantiator": "^1.0.2",
|
||||
"php": "^5.3|^7.0",
|
||||
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
|
||||
"sebastian/comparator": "^1.1",
|
||||
"sebastian/recursion-context": "^1.0|^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpspec/phpspec": "^2.0",
|
||||
"phpunit/phpunit": "^4.8 || ^5.6.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.6.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Prophecy\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Konstantin Kudryashov",
|
||||
"email": "ever.zet@gmail.com",
|
||||
"homepage": "http://everzet.com"
|
||||
},
|
||||
{
|
||||
"name": "Marcello Duarte",
|
||||
"email": "marcello.duarte@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Highly opinionated mocking framework for PHP 5.3+",
|
||||
"homepage": "https://github.com/phpspec/prophecy",
|
||||
"keywords": [
|
||||
"Double",
|
||||
"Dummy",
|
||||
"fake",
|
||||
"mock",
|
||||
"spy",
|
||||
"stub"
|
||||
],
|
||||
"time": "2016-11-21T14:58:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "2.2.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
|
||||
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"phpunit/php-file-iterator": "~1.3",
|
||||
"phpunit/php-text-template": "~1.2",
|
||||
"phpunit/php-token-stream": "~1.3",
|
||||
"sebastian/environment": "^1.3.2",
|
||||
"sebastian/version": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-xdebug": ">=2.1.4",
|
||||
"phpunit/phpunit": "~4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "*",
|
||||
"ext-xdebug": ">=2.2.1",
|
||||
"ext-xmlwriter": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sb@sebastian-bergmann.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
|
||||
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
|
||||
"keywords": [
|
||||
"coverage",
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2015-10-06T15:47:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
"version": "1.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
|
||||
"reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
|
||||
"reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sb@sebastian-bergmann.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
|
||||
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
|
||||
"keywords": [
|
||||
"filesystem",
|
||||
"iterator"
|
||||
],
|
||||
"time": "2016-10-03T07:40:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-text-template",
|
||||
"version": "1.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-text-template.git",
|
||||
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
|
||||
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Simple template engine.",
|
||||
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
|
||||
"keywords": [
|
||||
"template"
|
||||
],
|
||||
"time": "2015-06-21T13:50:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-timer",
|
||||
"version": "1.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-timer.git",
|
||||
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
|
||||
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4|~5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sb@sebastian-bergmann.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Utility class for timing",
|
||||
"homepage": "https://github.com/sebastianbergmann/php-timer/",
|
||||
"keywords": [
|
||||
"timer"
|
||||
],
|
||||
"time": "2016-05-12T18:03:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-token-stream",
|
||||
"version": "1.4.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
|
||||
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b",
|
||||
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-tokenizer": "*",
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
}
|
||||
],
|
||||
"description": "Wrapper around PHP's tokenizer extension.",
|
||||
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
|
||||
"keywords": [
|
||||
"tokenizer"
|
||||
],
|
||||
"time": "2016-11-15T14:06:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "4.8.35",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87",
|
||||
"reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-json": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-reflection": "*",
|
||||
"ext-spl": "*",
|
||||
"php": ">=5.3.3",
|
||||
"phpspec/prophecy": "^1.3.1",
|
||||
"phpunit/php-code-coverage": "~2.1",
|
||||
"phpunit/php-file-iterator": "~1.4",
|
||||
"phpunit/php-text-template": "~1.2",
|
||||
"phpunit/php-timer": "^1.0.6",
|
||||
"phpunit/phpunit-mock-objects": "~2.3",
|
||||
"sebastian/comparator": "~1.2.2",
|
||||
"sebastian/diff": "~1.2",
|
||||
"sebastian/environment": "~1.3",
|
||||
"sebastian/exporter": "~1.2",
|
||||
"sebastian/global-state": "~1.0",
|
||||
"sebastian/version": "~1.0",
|
||||
"symfony/yaml": "~2.1|~3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"phpunit/php-invoker": "~1.1"
|
||||
},
|
||||
"bin": [
|
||||
"phpunit"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "The PHP Unit Testing framework.",
|
||||
"homepage": "https://phpunit.de/",
|
||||
"keywords": [
|
||||
"phpunit",
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2017-02-06T05:18:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit-mock-objects",
|
||||
"version": "2.3.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
|
||||
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
|
||||
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/instantiator": "^1.0.2",
|
||||
"php": ">=5.3.3",
|
||||
"phpunit/php-text-template": "~1.2",
|
||||
"sebastian/exporter": "~1.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-soap": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sb@sebastian-bergmann.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Mock Object library for PHPUnit",
|
||||
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
|
||||
"keywords": [
|
||||
"mock",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2015-10-02T06:51:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/comparator",
|
||||
"version": "1.2.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/comparator.git",
|
||||
"reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
|
||||
"reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"sebastian/diff": "~1.2",
|
||||
"sebastian/exporter": "~1.2 || ~2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jeff Welch",
|
||||
"email": "whatthejeff@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Volker Dusch",
|
||||
"email": "github@wallbash.com"
|
||||
},
|
||||
{
|
||||
"name": "Bernhard Schussek",
|
||||
"email": "bschussek@2bepublished.at"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
}
|
||||
],
|
||||
"description": "Provides the functionality to compare PHP values for equality",
|
||||
"homepage": "http://www.github.com/sebastianbergmann/comparator",
|
||||
"keywords": [
|
||||
"comparator",
|
||||
"compare",
|
||||
"equality"
|
||||
],
|
||||
"time": "2017-01-29T09:50:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "1.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
|
||||
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.8"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kore Nordmann",
|
||||
"email": "mail@kore-nordmann.de"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
}
|
||||
],
|
||||
"description": "Diff implementation",
|
||||
"homepage": "https://github.com/sebastianbergmann/diff",
|
||||
"keywords": [
|
||||
"diff"
|
||||
],
|
||||
"time": "2015-12-08T07:14:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
"version": "1.3.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/environment.git",
|
||||
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
|
||||
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3.3 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8 || ^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
}
|
||||
],
|
||||
"description": "Provides functionality to handle HHVM/PHP environments",
|
||||
"homepage": "http://www.github.com/sebastianbergmann/environment",
|
||||
"keywords": [
|
||||
"Xdebug",
|
||||
"environment",
|
||||
"hhvm"
|
||||
],
|
||||
"time": "2016-08-18T05:49:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
"version": "1.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/exporter.git",
|
||||
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
|
||||
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"sebastian/recursion-context": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-mbstring": "*",
|
||||
"phpunit/phpunit": "~4.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jeff Welch",
|
||||
"email": "whatthejeff@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Volker Dusch",
|
||||
"email": "github@wallbash.com"
|
||||
},
|
||||
{
|
||||
"name": "Bernhard Schussek",
|
||||
"email": "bschussek@2bepublished.at"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
},
|
||||
{
|
||||
"name": "Adam Harvey",
|
||||
"email": "aharvey@php.net"
|
||||
}
|
||||
],
|
||||
"description": "Provides the functionality to export PHP variables for visualization",
|
||||
"homepage": "http://www.github.com/sebastianbergmann/exporter",
|
||||
"keywords": [
|
||||
"export",
|
||||
"exporter"
|
||||
],
|
||||
"time": "2016-06-17T09:04:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/global-state",
|
||||
"version": "1.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/global-state.git",
|
||||
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
|
||||
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.2"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-uopz": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
}
|
||||
],
|
||||
"description": "Snapshotting of global state",
|
||||
"homepage": "http://www.github.com/sebastianbergmann/global-state",
|
||||
"keywords": [
|
||||
"global state"
|
||||
],
|
||||
"time": "2015-10-12T03:26:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/recursion-context",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/recursion-context.git",
|
||||
"reference": "913401df809e99e4f47b27cdd781f4a258d58791"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
|
||||
"reference": "913401df809e99e4f47b27cdd781f4a258d58791",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jeff Welch",
|
||||
"email": "whatthejeff@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
},
|
||||
{
|
||||
"name": "Adam Harvey",
|
||||
"email": "aharvey@php.net"
|
||||
}
|
||||
],
|
||||
"description": "Provides functionality to recursively process PHP variables",
|
||||
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
||||
"time": "2015-11-11T19:50:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/version",
|
||||
"version": "1.0.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/version.git",
|
||||
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
|
||||
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
||||
"homepage": "https://github.com/sebastianbergmann/version",
|
||||
"time": "2015-06-21T13:59:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v2.8.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/322a8c2dfbca15ad6b1b27e182899f98ec0e0153",
|
||||
"reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.8-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2017-01-21T16:40:50+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"phpunit/phpunit": 0
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"platform-dev": []
|
||||
}
|
||||
+12
-6
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
@@ -6,15 +6,21 @@
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
stopOnFailure="false">
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory suffix="Test.php">./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">./lib</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
</include>
|
||||
<report>
|
||||
<html outputDirectory="build/coverage"/>
|
||||
<text outputFile="php://stdout"/>
|
||||
</report>
|
||||
</coverage>
|
||||
</phpunit>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
trait MightNotMakeAssertions
|
||||
{
|
||||
/**
|
||||
* This is a shim to support PHPUnit for php 5.6 and 7.0.
|
||||
*
|
||||
* It has to be named something that doesn't collide with existing
|
||||
* TestCase methods as we can't support PHP return types right now
|
||||
*/
|
||||
public function noAssertionsMade()
|
||||
{
|
||||
foreach (class_parents($this) as $parent) {
|
||||
if (method_exists($parent, 'expectNotToPerformAssertions')) {
|
||||
return parent::expectNotToPerformAssertions();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Qr;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RobThree\Auth\TwoFactorAuth;
|
||||
use RobThree\Auth\TwoFactorAuthException;
|
||||
|
||||
class IQRCodeProviderTest extends TestCase
|
||||
{
|
||||
private function DecodeDataUri($datauri)
|
||||
{
|
||||
if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
|
||||
return array(
|
||||
'mimetype' => $m['mimetype'],
|
||||
'encoding' => $m['encoding'],
|
||||
'data' => base64_decode($m['data'])
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function testTotpUriIsCorrect()
|
||||
{
|
||||
$qr = new TestQrProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
|
||||
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
|
||||
$this->assertEquals('test/test', $data['mimetype']);
|
||||
$this->assertEquals('base64', $data['encoding']);
|
||||
$this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']);
|
||||
}
|
||||
|
||||
public function testGetQRCodeImageAsDataUriThrowsOnInvalidSize()
|
||||
{
|
||||
$qr = new TestQrProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', $qr);
|
||||
|
||||
$this->expectException(TwoFactorAuthException::class);
|
||||
|
||||
$tfa->getQRCodeImageAsDataUri('Test', 'VMR466AB62ZBOKHE', 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Qr;
|
||||
|
||||
use RobThree\Auth\Providers\Qr\IQRCodeProvider;
|
||||
|
||||
class TestQrProvider implements IQRCodeProvider
|
||||
{
|
||||
public function getQRCodeImage($qrtext, $size)
|
||||
{
|
||||
return $qrtext . '@' . $size;
|
||||
}
|
||||
|
||||
public function getMimeType()
|
||||
{
|
||||
return 'test/test';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Tests\MightNotMakeAssertions;
|
||||
use RobThree\Auth\Providers\Rng\CSRNGProvider;
|
||||
|
||||
class CSRNGProviderTest extends TestCase
|
||||
{
|
||||
use NeedsRngLengths, MightNotMakeAssertions;
|
||||
|
||||
/**
|
||||
* @requires function random_bytes
|
||||
*/
|
||||
public function testCSRNGProvidersReturnExpectedNumberOfBytes()
|
||||
{
|
||||
if (function_exists('random_bytes')) {
|
||||
$rng = new CSRNGProvider();
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
$this->assertTrue($rng->isCryptographicallySecure());
|
||||
} else {
|
||||
$this->noAssertionsMade();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RobThree\Auth\Providers\Rng\HashRNGProvider;
|
||||
|
||||
class HashRNGProviderTest extends TestCase
|
||||
{
|
||||
use NeedsRngLengths;
|
||||
|
||||
public function testHashRNGProvidersReturnExpectedNumberOfBytes()
|
||||
{
|
||||
$rng = new HashRNGProvider();
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
|
||||
$this->assertFalse($rng->isCryptographicallySecure());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RobThree\Auth\TwoFactorAuth;
|
||||
use RobThree\Auth\TwoFactorAuthException;
|
||||
|
||||
class IRNGProviderTest extends TestCase
|
||||
{
|
||||
public function testCreateSecretThrowsOnInsecureRNGProvider()
|
||||
{
|
||||
$rng = new TestRNGProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
|
||||
|
||||
$this->expectException(TwoFactorAuthException::class);
|
||||
$tfa->createSecret();
|
||||
}
|
||||
|
||||
public function testCreateSecretOverrideSecureDoesNotThrowOnInsecureRNG()
|
||||
{
|
||||
$rng = new TestRNGProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret(80, false));
|
||||
}
|
||||
|
||||
public function testCreateSecretDoesNotThrowOnSecureRNGProvider()
|
||||
{
|
||||
$rng = new TestRNGProvider(true);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret());
|
||||
}
|
||||
|
||||
public function testCreateSecretGeneratesDesiredAmountOfEntropy()
|
||||
{
|
||||
$rng = new TestRNGProvider(true);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
|
||||
$this->assertEquals('A', $tfa->createSecret(5));
|
||||
$this->assertEquals('AB', $tfa->createSecret(6));
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128));
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160));
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320));
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Tests\MightNotMakeAssertions;
|
||||
use RobThree\Auth\Providers\Rng\MCryptRNGProvider;
|
||||
|
||||
class MCryptRNGProviderTest extends TestCase
|
||||
{
|
||||
use NeedsRngLengths, MightNotMakeAssertions;
|
||||
|
||||
/**
|
||||
* @requires function mcrypt_create_iv
|
||||
*/
|
||||
public function testMCryptRNGProvidersReturnExpectedNumberOfBytes()
|
||||
{
|
||||
if (function_exists('mcrypt_create_iv')) {
|
||||
$rng = new MCryptRNGProvider();
|
||||
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
|
||||
$this->assertTrue($rng->isCryptographicallySecure());
|
||||
} else {
|
||||
$this->noAssertionsMade();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
trait NeedsRngLengths
|
||||
{
|
||||
protected $rngTestLengths = array(1, 16, 32, 256);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RobThree\Auth\Providers\Rng\OpenSSLRNGProvider;
|
||||
|
||||
class OpenSSLRNGProviderTest extends TestCase
|
||||
{
|
||||
use NeedsRngLengths;
|
||||
|
||||
public function testStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes()
|
||||
{
|
||||
$rng = new OpenSSLRNGProvider(true);
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
|
||||
$this->assertTrue($rng->isCryptographicallySecure());
|
||||
}
|
||||
|
||||
public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes()
|
||||
{
|
||||
$rng = new OpenSSLRNGProvider(false);
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
|
||||
$this->assertFalse($rng->isCryptographicallySecure());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
use RobThree\Auth\Providers\Rng\IRNGProvider;
|
||||
|
||||
class TestRNGProvider implements IRNGProvider
|
||||
{
|
||||
private $isSecure;
|
||||
|
||||
function __construct($isSecure = false)
|
||||
{
|
||||
$this->isSecure = $isSecure;
|
||||
}
|
||||
|
||||
public function getRandomBytes($bytecount)
|
||||
{
|
||||
$result = '';
|
||||
|
||||
for ($i = 0; $i < $bytecount; $i++) {
|
||||
$result .= chr($i);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function isCryptographicallySecure()
|
||||
{
|
||||
return $this->isSecure;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Time;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Tests\MightNotMakeAssertions;
|
||||
use RobThree\Auth\TwoFactorAuthException;
|
||||
use RobThree\Auth\TwoFactorAuth;
|
||||
|
||||
class ITimeProviderTest extends TestCase
|
||||
{
|
||||
use MightNotMakeAssertions;
|
||||
|
||||
public function testEnsureCorrectTimeDoesNotThrowForCorrectTime()
|
||||
{
|
||||
$tpr1 = new TestTimeProvider(123);
|
||||
$tpr2 = new TestTimeProvider(128);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
|
||||
$tfa->ensureCorrectTime(array($tpr2)); // 128 - 123 = 5 => within default leniency
|
||||
|
||||
$this->noAssertionsMade();
|
||||
}
|
||||
|
||||
public function testEnsureCorrectTimeThrowsOnIncorrectTime()
|
||||
{
|
||||
$tpr1 = new TestTimeProvider(123);
|
||||
$tpr2 = new TestTimeProvider(124);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
|
||||
|
||||
$this->expectException(TwoFactorAuthException::class);
|
||||
|
||||
$tfa->ensureCorrectTime(array($tpr2), 0); // We force a leniency of 0, 124-123 = 1 so this should throw
|
||||
}
|
||||
|
||||
public function testEnsureDefaultTimeProviderReturnsCorrectTime()
|
||||
{
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1');
|
||||
$tfa->ensureCorrectTime(array(new TestTimeProvider(time())), 1); // Use a leniency of 1, should the time change between both time() calls
|
||||
|
||||
$this->noAssertionsMade();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers\Time;
|
||||
|
||||
use RobThree\Auth\Providers\Time\ITimeProvider;
|
||||
|
||||
class TestTimeProvider implements ITimeProvider
|
||||
{
|
||||
private $time;
|
||||
|
||||
function __construct($time)
|
||||
{
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
public function getTime()
|
||||
{
|
||||
return $this->time;
|
||||
}
|
||||
}
|
||||
+70
-279
@@ -1,221 +1,121 @@
|
||||
<?php
|
||||
require_once 'lib/TwoFactorAuth.php';
|
||||
require_once 'lib/TwoFactorAuthException.php';
|
||||
|
||||
require_once 'lib/Providers/Qr/IQRCodeProvider.php';
|
||||
require_once 'lib/Providers/Qr/BaseHTTPQRCodeProvider.php';
|
||||
require_once 'lib/Providers/Qr/ImageChartsQRCodeProvider.php';
|
||||
require_once 'lib/Providers/Qr/QRException.php';
|
||||
|
||||
require_once 'lib/Providers/Rng/IRNGProvider.php';
|
||||
require_once 'lib/Providers/Rng/RNGException.php';
|
||||
require_once 'lib/Providers/Rng/CSRNGProvider.php';
|
||||
require_once 'lib/Providers/Rng/MCryptRNGProvider.php';
|
||||
require_once 'lib/Providers/Rng/OpenSSLRNGProvider.php';
|
||||
require_once 'lib/Providers/Rng/HashRNGProvider.php';
|
||||
require_once 'lib/Providers/Rng/RNGException.php';
|
||||
|
||||
require_once 'lib/Providers/Time/ITimeProvider.php';
|
||||
require_once 'lib/Providers/Time/LocalMachineTimeProvider.php';
|
||||
require_once 'lib/Providers/Time/HttpTimeProvider.php';
|
||||
require_once 'lib/Providers/Time/NTPTimeProvider.php';
|
||||
require_once 'lib/Providers/Time/TimeException.php';
|
||||
namespace Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RobThree\Auth\TwoFactorAuthException;
|
||||
use RobThree\Auth\TwoFactorAuth;
|
||||
use RobThree\Auth\Providers\Qr\IQRCodeProvider;
|
||||
use RobThree\Auth\Providers\Rng\IRNGProvider;
|
||||
use RobThree\Auth\Providers\Time\ITimeProvider;
|
||||
|
||||
|
||||
class TwoFactorAuthTest extends PHPUnit\Framework\TestCase
|
||||
class TwoFactorAuthTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \RobThree\Auth\TwoFactorAuthException
|
||||
*/
|
||||
public function testConstructorThrowsOnInvalidDigits() {
|
||||
use MightNotMakeAssertions;
|
||||
|
||||
public function testConstructorThrowsOnInvalidDigits()
|
||||
{
|
||||
$this->expectException(TwoFactorAuthException::class);
|
||||
|
||||
new TwoFactorAuth('Test', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RobThree\Auth\TwoFactorAuthException
|
||||
*/
|
||||
public function testConstructorThrowsOnInvalidPeriod() {
|
||||
public function testConstructorThrowsOnInvalidPeriod()
|
||||
{
|
||||
$this->expectException(TwoFactorAuthException::class);
|
||||
|
||||
new TwoFactorAuth('Test', 6, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RobThree\Auth\TwoFactorAuthException
|
||||
*/
|
||||
public function testConstructorThrowsOnInvalidAlgorithm() {
|
||||
public function testConstructorThrowsOnInvalidAlgorithm()
|
||||
{
|
||||
$this->expectException(TwoFactorAuthException::class);
|
||||
|
||||
new TwoFactorAuth('Test', 6, 30, 'xxx');
|
||||
}
|
||||
|
||||
public function testGetCodeReturnsCorrectResults() {
|
||||
|
||||
public function testGetCodeReturnsCorrectResults()
|
||||
{
|
||||
$tfa = new TwoFactorAuth('Test');
|
||||
$this->assertEquals('543160', $tfa->getCode('VMR466AB62ZBOKHE', 1426847216));
|
||||
$this->assertEquals('538532', $tfa->getCode('VMR466AB62ZBOKHE', 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RobThree\Auth\TwoFactorAuthException
|
||||
*/
|
||||
public function testCreateSecretThrowsOnInsecureRNGProvider() {
|
||||
$rng = new TestRNGProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
|
||||
$tfa->createSecret();
|
||||
}
|
||||
|
||||
public function testCreateSecretOverrideSecureDoesNotThrowOnInsecureRNG() {
|
||||
$rng = new TestRNGProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret(80, false));
|
||||
}
|
||||
|
||||
public function testCreateSecretDoesNotThrowOnSecureRNGProvider() {
|
||||
$rng = new TestRNGProvider(true);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret());
|
||||
}
|
||||
|
||||
public function testCreateSecretGeneratesDesiredAmountOfEntropy() {
|
||||
$rng = new TestRNGProvider(true);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
|
||||
$this->assertEquals('A', $tfa->createSecret(5));
|
||||
$this->assertEquals('AB', $tfa->createSecret(6));
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128));
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160));
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320));
|
||||
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321));
|
||||
}
|
||||
|
||||
public function testEnsureCorrectTimeDoesNotThrowForCorrectTime() {
|
||||
$tpr1 = new TestTimeProvider(123);
|
||||
$tpr2 = new TestTimeProvider(128);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
|
||||
$tfa->ensureCorrectTime(array($tpr2)); // 128 - 123 = 5 => within default leniency
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RobThree\Auth\TwoFactorAuthException
|
||||
*/
|
||||
public function testEnsureCorrectTimeThrowsOnIncorrectTime() {
|
||||
$tpr1 = new TestTimeProvider(123);
|
||||
$tpr2 = new TestTimeProvider(124);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
|
||||
$tfa->ensureCorrectTime(array($tpr2), 0); // We force a leniency of 0, 124-123 = 1 so this should throw
|
||||
}
|
||||
|
||||
|
||||
public function testEnsureDefaultTimeProviderReturnsCorrectTime() {
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1');
|
||||
$tfa->ensureCorrectTime(array(new TestTimeProvider(time())), 1); // Use a leniency of 1, should the time change between both time() calls
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testEnsureAllTimeProvidersReturnCorrectTime() {
|
||||
public function testEnsureAllTimeProvidersReturnCorrectTime()
|
||||
{
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1');
|
||||
$tfa->ensureCorrectTime(array(
|
||||
new RobThree\Auth\Providers\Time\NTPTimeProvider(), // Uses pool.ntp.org by default
|
||||
//new RobThree\Auth\Providers\Time\NTPTimeProvider('time.google.com'), // Somehow time.google.com and time.windows.com make travis timeout??
|
||||
new RobThree\Auth\Providers\Time\HttpTimeProvider(), // Uses google.com by default
|
||||
new RobThree\Auth\Providers\Time\HttpTimeProvider('https://github.com'),
|
||||
new RobThree\Auth\Providers\Time\HttpTimeProvider('https://yahoo.com'),
|
||||
new \RobThree\Auth\Providers\Time\NTPTimeProvider(), // Uses pool.ntp.org by default
|
||||
//new \RobThree\Auth\Providers\Time\NTPTimeProvider('time.google.com'), // Somehow time.google.com and time.windows.com make travis timeout??
|
||||
new \RobThree\Auth\Providers\Time\HttpTimeProvider(), // Uses google.com by default
|
||||
new \RobThree\Auth\Providers\Time\HttpTimeProvider('https://github.com'),
|
||||
new \RobThree\Auth\Providers\Time\HttpTimeProvider('https://yahoo.com'),
|
||||
));
|
||||
$this->assertTrue(true);
|
||||
$this->noAssertionsMade();
|
||||
}
|
||||
|
||||
public function testVerifyCodeWorksCorrectly() {
|
||||
|
||||
public function testVerifyCodeWorksCorrectly()
|
||||
{
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30);
|
||||
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847190));
|
||||
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 29)); //Test discrepancy
|
||||
$this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 30)); //Test discrepancy
|
||||
$this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 - 1)); //Test discrepancy
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847190));
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 29)); //Test discrepancy
|
||||
$this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 30)); //Test discrepancy
|
||||
$this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 - 1)); //Test discrepancy
|
||||
|
||||
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 0)); //Test discrepancy
|
||||
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 35)); //Test discrepancy
|
||||
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 35)); //Test discrepancy
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 0)); //Test discrepancy
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 35)); //Test discrepancy
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 35)); //Test discrepancy
|
||||
|
||||
$this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 65)); //Test discrepancy
|
||||
$this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 65)); //Test discrepancy
|
||||
$this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 65)); //Test discrepancy
|
||||
$this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 65)); //Test discrepancy
|
||||
|
||||
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 + 65)); //Test discrepancy
|
||||
$this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 - 65)); //Test discrepancy
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 + 65)); //Test discrepancy
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 - 65)); //Test discrepancy
|
||||
}
|
||||
|
||||
public function testVerifyCorrectTimeSliceIsReturned() {
|
||||
public function testVerifyCorrectTimeSliceIsReturned()
|
||||
{
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30);
|
||||
|
||||
// We test with discrepancy 3 (so total of 7 codes: c-3, c-2, c-1, c, c+1, c+2, c+3
|
||||
// Ensure each corresponding timeslice is returned correctly
|
||||
$this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '534113', 3, 1426847190, $timeslice1));
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '534113', 3, 1426847190, $timeslice1));
|
||||
$this->assertEquals(47561570, $timeslice1);
|
||||
$this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '819652', 3, 1426847190, $timeslice2));
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '819652', 3, 1426847190, $timeslice2));
|
||||
$this->assertEquals(47561571, $timeslice2);
|
||||
$this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '915954', 3, 1426847190, $timeslice3));
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '915954', 3, 1426847190, $timeslice3));
|
||||
$this->assertEquals(47561572, $timeslice3);
|
||||
$this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 3, 1426847190, $timeslice4));
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 3, 1426847190, $timeslice4));
|
||||
$this->assertEquals(47561573, $timeslice4);
|
||||
$this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '348401', 3, 1426847190, $timeslice5));
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '348401', 3, 1426847190, $timeslice5));
|
||||
$this->assertEquals(47561574, $timeslice5);
|
||||
$this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '648525', 3, 1426847190, $timeslice6));
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '648525', 3, 1426847190, $timeslice6));
|
||||
$this->assertEquals(47561575, $timeslice6);
|
||||
$this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '170645', 3, 1426847190, $timeslice7));
|
||||
$this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '170645', 3, 1426847190, $timeslice7));
|
||||
$this->assertEquals(47561576, $timeslice7);
|
||||
|
||||
// Incorrect code should return false and a 0 timeslice
|
||||
$this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '111111', 3, 1426847190, $timeslice8));
|
||||
$this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '111111', 3, 1426847190, $timeslice8));
|
||||
$this->assertEquals(0, $timeslice8);
|
||||
}
|
||||
|
||||
public function testTotpUriIsCorrect() {
|
||||
$qr = new TestQrProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
|
||||
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
|
||||
$this->assertEquals('test/test', $data['mimetype']);
|
||||
$this->assertEquals('base64', $data['encoding']);
|
||||
$this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RobThree\Auth\TwoFactorAuthException
|
||||
*/
|
||||
public function testGetQRCodeImageAsDataUriThrowsOnInvalidSize() {
|
||||
$qr = new TestQrProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', $qr);
|
||||
$tfa->getQRCodeImageAsDataUri('Test', 'VMR466AB62ZBOKHE', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RobThree\Auth\TwoFactorAuthException
|
||||
*/
|
||||
public function testGetCodeThrowsOnInvalidBase32String1() {
|
||||
public function testGetCodeThrowsOnInvalidBase32String1()
|
||||
{
|
||||
$tfa = new TwoFactorAuth('Test');
|
||||
|
||||
$this->expectException(TwoFactorAuthException::class);
|
||||
|
||||
$tfa->getCode('FOO1BAR8BAZ9'); //1, 8 & 9 are invalid chars
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RobThree\Auth\TwoFactorAuthException
|
||||
*/
|
||||
public function testGetCodeThrowsOnInvalidBase32String2() {
|
||||
public function testGetCodeThrowsOnInvalidBase32String2()
|
||||
{
|
||||
$tfa = new TwoFactorAuth('Test');
|
||||
|
||||
$this->expectException(TwoFactorAuthException::class);
|
||||
|
||||
$tfa->getCode('mzxw6==='); //Lowercase
|
||||
}
|
||||
|
||||
public function testKnownBase32DecodeTestVectors() {
|
||||
public function testKnownBase32DecodeTestVectors()
|
||||
{
|
||||
// We usually don't test internals (e.g. privates) but since we rely heavily on base32 decoding and don't want
|
||||
// to expose this method nor do we want to give people the possibility of implementing / providing their own base32
|
||||
// decoding/decoder (as we do with Rng/QR providers for example) we simply test the private base32Decode() method
|
||||
@@ -229,7 +129,7 @@ class TwoFactorAuthTest extends PHPUnit\Framework\TestCase
|
||||
// Dave Thomas and Andy Hunt -- "Pragmatic Unit Testing
|
||||
$tfa = new TwoFactorAuth('Test');
|
||||
|
||||
$method = new ReflectionMethod('RobThree\Auth\TwoFactorAuth', 'base32Decode');
|
||||
$method = new \ReflectionMethod(TwoFactorAuth::class, 'base32Decode');
|
||||
$method->setAccessible(true);
|
||||
|
||||
// Test vectors from: https://tools.ietf.org/html/rfc4648#page-12
|
||||
@@ -242,14 +142,15 @@ class TwoFactorAuthTest extends PHPUnit\Framework\TestCase
|
||||
$this->assertEquals('foobar', $method->invoke($tfa, 'MZXW6YTBOI======'));
|
||||
}
|
||||
|
||||
public function testKnownBase32DecodeUnpaddedTestVectors() {
|
||||
public function testKnownBase32DecodeUnpaddedTestVectors()
|
||||
{
|
||||
// See testKnownBase32DecodeTestVectors() for the rationale behind testing the private base32Decode() method.
|
||||
// This test ensures that strings without the padding-char ('=') are also decoded correctly.
|
||||
// https://tools.ietf.org/html/rfc4648#page-4:
|
||||
// "In some circumstances, the use of padding ("=") in base-encoded data is not required or used."
|
||||
$tfa = new TwoFactorAuth('Test');
|
||||
|
||||
$method = new ReflectionMethod('RobThree\Auth\TwoFactorAuth', 'base32Decode');
|
||||
$method = new \ReflectionMethod(TwoFactorAuth::class, 'base32Decode');
|
||||
$method->setAccessible(true);
|
||||
|
||||
// Test vectors from: https://tools.ietf.org/html/rfc4648#page-12
|
||||
@@ -262,8 +163,8 @@ class TwoFactorAuthTest extends PHPUnit\Framework\TestCase
|
||||
$this->assertEquals('foobar', $method->invoke($tfa, 'MZXW6YTBOI'));
|
||||
}
|
||||
|
||||
|
||||
public function testKnownTestVectors_sha1() {
|
||||
public function testKnownTestVectors_sha1()
|
||||
{
|
||||
//Known test vectors for SHA1: https://tools.ietf.org/html/rfc6238#page-15
|
||||
$secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ'; //== base32encode('12345678901234567890')
|
||||
$tfa = new TwoFactorAuth('Test', 8, 30, 'sha1');
|
||||
@@ -275,7 +176,8 @@ class TwoFactorAuthTest extends PHPUnit\Framework\TestCase
|
||||
$this->assertEquals('65353130', $tfa->getCode($secret, 20000000000));
|
||||
}
|
||||
|
||||
public function testKnownTestVectors_sha256() {
|
||||
public function testKnownTestVectors_sha256()
|
||||
{
|
||||
//Known test vectors for SHA256: https://tools.ietf.org/html/rfc6238#page-15
|
||||
$secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZA'; //== base32encode('12345678901234567890123456789012')
|
||||
$tfa = new TwoFactorAuth('Test', 8, 30, 'sha256');
|
||||
@@ -287,7 +189,8 @@ class TwoFactorAuthTest extends PHPUnit\Framework\TestCase
|
||||
$this->assertEquals('77737706', $tfa->getCode($secret, 20000000000));
|
||||
}
|
||||
|
||||
public function testKnownTestVectors_sha512() {
|
||||
public function testKnownTestVectors_sha512()
|
||||
{
|
||||
//Known test vectors for SHA512: https://tools.ietf.org/html/rfc6238#page-15
|
||||
$secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNA'; //== base32encode('1234567890123456789012345678901234567890123456789012345678901234')
|
||||
$tfa = new TwoFactorAuth('Test', 8, 30, 'sha512');
|
||||
@@ -298,116 +201,4 @@ class TwoFactorAuthTest extends PHPUnit\Framework\TestCase
|
||||
$this->assertEquals('38618901', $tfa->getCode($secret, 2000000000));
|
||||
$this->assertEquals('47863826', $tfa->getCode($secret, 20000000000));
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires function random_bytes
|
||||
*/
|
||||
public function testCSRNGProvidersReturnExpectedNumberOfBytes() {
|
||||
$rng = new \RobThree\Auth\Providers\Rng\CSRNGProvider();
|
||||
foreach ($this->getRngTestLengths() as $l)
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
$this->assertEquals(true, $rng->isCryptographicallySecure());
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires function hash_algos
|
||||
* @requires function hash
|
||||
*/
|
||||
public function testHashRNGProvidersReturnExpectedNumberOfBytes() {
|
||||
$rng = new \RobThree\Auth\Providers\Rng\HashRNGProvider();
|
||||
foreach ($this->getRngTestLengths() as $l)
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
$this->assertEquals(false, $rng->isCryptographicallySecure());
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires function mcrypt_create_iv
|
||||
*/
|
||||
public function testMCryptRNGProvidersReturnExpectedNumberOfBytes() {
|
||||
if (function_exists('mcrypt_create_iv')) {
|
||||
$rng = new \RobThree\Auth\Providers\Rng\MCryptRNGProvider();
|
||||
foreach ($this->getRngTestLengths() as $l)
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
$this->assertEquals(true, $rng->isCryptographicallySecure());
|
||||
}
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires function openssl_random_pseudo_bytes
|
||||
*/
|
||||
public function testStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() {
|
||||
$rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(true);
|
||||
foreach ($this->getRngTestLengths() as $l)
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
$this->assertEquals(true, $rng->isCryptographicallySecure());
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires function openssl_random_pseudo_bytes
|
||||
*/
|
||||
public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() {
|
||||
$rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(false);
|
||||
foreach ($this->getRngTestLengths() as $l)
|
||||
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||
$this->assertEquals(false, $rng->isCryptographicallySecure());
|
||||
}
|
||||
|
||||
|
||||
private function getRngTestLengths() {
|
||||
return array(1, 16, 32, 256);
|
||||
}
|
||||
|
||||
private function DecodeDataUri($datauri) {
|
||||
if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
|
||||
return array(
|
||||
'mimetype' => $m['mimetype'],
|
||||
'encoding' => $m['encoding'],
|
||||
'data' => base64_decode($m['data'])
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class TestRNGProvider implements IRNGProvider {
|
||||
private $isSecure;
|
||||
|
||||
function __construct($isSecure = false) {
|
||||
$this->isSecure = $isSecure;
|
||||
}
|
||||
|
||||
public function getRandomBytes($bytecount) {
|
||||
$result = '';
|
||||
for ($i=0; $i<$bytecount; $i++)
|
||||
$result.=chr($i);
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
public function isCryptographicallySecure() {
|
||||
return $this->isSecure;
|
||||
}
|
||||
}
|
||||
|
||||
class TestQrProvider implements IQRCodeProvider {
|
||||
public function getQRCodeImage($qrtext, $size) {
|
||||
return $qrtext . '@' . $size;
|
||||
}
|
||||
|
||||
public function getMimeType() {
|
||||
return 'test/test';
|
||||
}
|
||||
}
|
||||
|
||||
class TestTimeProvider implements ITimeProvider {
|
||||
private $time;
|
||||
|
||||
function __construct($time) {
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
public function getTime() {
|
||||
return $this->time;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user