This commit is contained in:
2025-10-09 17:41:57 +00:00
commit 7a3b2960f8
146 changed files with 34948 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
service_name: travis-ci
coverage_clover: build/logs/clover.xml
json_path: coveralls-upload.json
+10
View File
@@ -0,0 +1,10 @@
composer.phar
/vendor/
# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
# composer.lock
nbproject/
build/
.phpunit.result.cache
infection.log
+23
View File
@@ -0,0 +1,23 @@
language: php
php:
- 7.3
- 7.4
- 8.0
- nightly
matrix:
allow_failures:
- php: nightly
install:
- phpenv config-rm xdebug.ini || true
- travis_retry composer install --prefer-dist -n
script:
- mkdir -p build/logs
- phpdbg -qrr vendor/bin/phpunit
after_success:
- composer require php-coveralls/php-coveralls
- travis_retry vendor/bin/php-coveralls -v
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Boris Momčilović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+32
View File
@@ -0,0 +1,32 @@
# php-keccak [![Build Status](https://travis-ci.org/kornrunner/php-keccak.svg?branch=master)](https://travis-ci.org/kornrunner/php-keccak) [![Build status](https://ci.appveyor.com/api/projects/status/48isd8g6gov29wba/branch/master?svg=true)](https://ci.appveyor.com/project/kornrunner/php-keccak/branch/master) [![Coverage Status](https://coveralls.io/repos/github/kornrunner/php-keccak/badge.svg?branch=master)](https://coveralls.io/github/kornrunner/php-keccak?branch=master) [![Latest Stable Version](https://poser.pugx.org/kornrunner/keccak/v/stable)](https://packagist.org/packages/kornrunner/keccak)
Pure PHP implementation of Keccak (SHA-3)
## Usage
```php
<?php
use kornrunner\Keccak;
Keccak::hash('', 224);
// f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd
Keccak::hash('', 256);
// c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
Keccak::hash('', 384);
// 2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff
Keccak::hash('', 512);
// 0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e
Keccak::shake('', 128, 256);
// 7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26
Keccak::shake('', 256, 512);
// 46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be
```
[![Ethereum](https://user-images.githubusercontent.com/725986/61891022-0d0c7f00-af09-11e9-829f-096c039bbbfa.png) 0x9c7b7a00972121fb843af7af74526d7eb585b171][Ethereum]
[Ethereum]: https://etherscan.io/address/0x9c7b7a00972121fb843af7af74526d7eb585b171 "Donate with Ethereum"
+48
View File
@@ -0,0 +1,48 @@
build: false
shallow_clone: true
clone_folder: c:\php-keccak
platform: x64
cache:
- c:\php -> appveyor.yml
- vendor -> composer.lock
environment:
matrix:
- PHP_VERSION: '7.3.7'
PHP_DOWNLOAD_URL: 'https://windows.php.net/downloads/releases/archives/php-7.3.7-nts-Win32-VC15-x64.zip'
- PHP_VERSION: '7.4.3'
PHP_DOWNLOAD_URL: 'https://windows.php.net/downloads/releases/archives/php-7.4.3-nts-Win32-vc15-x64.zip'
- PHP_VERSION: '8.0.0'
PHP_DOWNLOAD_URL: 'https://windows.php.net/downloads/releases/php-8.0.0-nts-Win32-vs16-x64.zip'
matrix:
fast_finish: true
init:
- SET PATH=c:\php\%PHP_VERSION%;%PATH%
- set COMPOSER_NO_INTERACTION=1
install:
- IF NOT EXIST c:\php mkdir c:\php
- IF NOT EXIST c:\php\%PHP_VERSION% mkdir c:\php\%PHP_VERSION%
- cd c:\php\%PHP_VERSION%
- IF NOT EXIST php-installed.txt curl --fail --location --silent --show-error -o php.zip %PHP_DOWNLOAD_URL%
- IF NOT EXIST php-installed.txt 7z x php.zip -y
- IF NOT EXIST php-installed.txt del /Q *.zip
- IF NOT EXIST php-installed.txt copy /Y php.ini-development php.ini
- IF NOT EXIST php-installed.txt echo max_execution_time=1200 >> php.ini
- IF NOT EXIST php-installed.txt echo date.timezone="UTC" >> php.ini
- IF NOT EXIST php-installed.txt echo extension_dir=ext >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_openssl.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_mbstring.dll >> php.ini
- IF NOT EXIST php-installed.txt appveyor DownloadFile https://getcomposer.org/composer.phar
- IF NOT EXIST php-installed.txt echo @php %%~dp0composer.phar %%* > composer.bat
- IF NOT EXIST php-installed.txt type nul >> php-installed.txt
- cd c:\php-keccak
test_script:
- composer install
- vendor/bin/phpunit.bat --coverage-text
+29
View File
@@ -0,0 +1,29 @@
{
"name": "kornrunner/keccak",
"description": "Pure PHP implementation of Keccak",
"keywords": ["keccak", "sha-3", "sha3-256"],
"license": "MIT",
"authors": [
{
"name": "Boris Momcilovic",
"homepage": "https://github.com/kornrunner/php-keccak"
}
],
"require": {
"php": ">=7.3",
"symfony/polyfill-mbstring": "^1.8"
},
"autoload": {
"psr-4": {
"kornrunner\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"kornrunner\\": "test"
}
},
"require-dev": {
"phpunit/phpunit": "^8.2"
}
}
+1870
View File
File diff suppressed because it is too large Load Diff
+14
View File
@@ -0,0 +1,14 @@
{
"timeout": 10,
"source": {
"directories": [
"src"
]
},
"logs": {
"text": "infection.log"
},
"mutators": {
"@default": true
}
}
+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Keccak Test Suite">
<directory>test</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<logging>
<log type="tap" target="build/report.tap"/>
<log type="junit" target="build/report.junit.xml"/>
<log type="coverage-html" target="build/coverage"/>
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
</phpunit>
+312
View File
@@ -0,0 +1,312 @@
<?php
namespace kornrunner;
use Exception;
use function mb_strlen;
use function mb_substr;
final class Keccak
{
private const KECCAK_ROUNDS = 24;
private const LFSR = 0x01;
private const ENCODING = '8bit';
private static $keccakf_rotc = [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44];
private static $keccakf_piln = [10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12,2, 20, 14, 22, 9, 6, 1];
private static $x64 = (PHP_INT_SIZE === 8);
private static function keccakf64(&$st, $rounds): void {
$keccakf_rndc = [
[0x00000000, 0x00000001], [0x00000000, 0x00008082], [0x80000000, 0x0000808a], [0x80000000, 0x80008000],
[0x00000000, 0x0000808b], [0x00000000, 0x80000001], [0x80000000, 0x80008081], [0x80000000, 0x00008009],
[0x00000000, 0x0000008a], [0x00000000, 0x00000088], [0x00000000, 0x80008009], [0x00000000, 0x8000000a],
[0x00000000, 0x8000808b], [0x80000000, 0x0000008b], [0x80000000, 0x00008089], [0x80000000, 0x00008003],
[0x80000000, 0x00008002], [0x80000000, 0x00000080], [0x00000000, 0x0000800a], [0x80000000, 0x8000000a],
[0x80000000, 0x80008081], [0x80000000, 0x00008080], [0x00000000, 0x80000001], [0x80000000, 0x80008008]
];
$bc = [];
for ($round = 0; $round < $rounds; $round++) {
// Theta
for ($i = 0; $i < 5; $i++) {
$bc[$i] = [
$st[$i][0] ^ $st[$i + 5][0] ^ $st[$i + 10][0] ^ $st[$i + 15][0] ^ $st[$i + 20][0],
$st[$i][1] ^ $st[$i + 5][1] ^ $st[$i + 10][1] ^ $st[$i + 15][1] ^ $st[$i + 20][1]
];
}
for ($i = 0; $i < 5; $i++) {
$t = [
$bc[($i + 4) % 5][0] ^ (($bc[($i + 1) % 5][0] << 1) | ($bc[($i + 1) % 5][1] >> 31)) & (0xFFFFFFFF),
$bc[($i + 4) % 5][1] ^ (($bc[($i + 1) % 5][1] << 1) | ($bc[($i + 1) % 5][0] >> 31)) & (0xFFFFFFFF)
];
for ($j = 0; $j < 25; $j += 5) {
$st[$j + $i] = [
$st[$j + $i][0] ^ $t[0],
$st[$j + $i][1] ^ $t[1]
];
}
}
// Rho Pi
$t = $st[1];
for ($i = 0; $i < 24; $i++) {
$j = self::$keccakf_piln[$i];
$bc[0] = $st[$j];
$n = self::$keccakf_rotc[$i];
$hi = $t[0];
$lo = $t[1];
if ($n >= 32) {
$n -= 32;
$hi = $t[1];
$lo = $t[0];
}
$st[$j] =[
(($hi << $n) | ($lo >> (32 - $n))) & (0xFFFFFFFF),
(($lo << $n) | ($hi >> (32 - $n))) & (0xFFFFFFFF)
];
$t = $bc[0];
}
// Chi
for ($j = 0; $j < 25; $j += 5) {
for ($i = 0; $i < 5; $i++) {
$bc[$i] = $st[$j + $i];
}
for ($i = 0; $i < 5; $i++) {
$st[$j + $i] = [
$st[$j + $i][0] ^ ~$bc[($i + 1) % 5][0] & $bc[($i + 2) % 5][0],
$st[$j + $i][1] ^ ~$bc[($i + 1) % 5][1] & $bc[($i + 2) % 5][1]
];
}
}
// Iota
$st[0] = [
$st[0][0] ^ $keccakf_rndc[$round][0],
$st[0][1] ^ $keccakf_rndc[$round][1]
];
}
}
private static function keccak64($in_raw, int $capacity, int $outputlength, $suffix, bool $raw_output): string {
$capacity /= 8;
$inlen = mb_strlen($in_raw, self::ENCODING);
$rsiz = 200 - 2 * $capacity;
$rsizw = $rsiz / 8;
$st = [];
for ($i = 0; $i < 25; $i++) {
$st[] = [0, 0];
}
for ($in_t = 0; $inlen >= $rsiz; $inlen -= $rsiz, $in_t += $rsiz) {
for ($i = 0; $i < $rsizw; $i++) {
$t = unpack('V*', mb_substr($in_raw, intval($i * 8 + $in_t), 8, self::ENCODING));
$st[$i] = [
$st[$i][0] ^ $t[2],
$st[$i][1] ^ $t[1]
];
}
self::keccakf64($st, self::KECCAK_ROUNDS);
}
$temp = mb_substr($in_raw, (int) $in_t, (int) $inlen, self::ENCODING);
$temp = str_pad($temp, (int) $rsiz, "\x0", STR_PAD_RIGHT);
$temp = substr_replace($temp, chr($suffix), $inlen, 1);
$temp = substr_replace($temp, chr(ord($temp[intval($rsiz - 1)]) | 0x80), $rsiz - 1, 1);
for ($i = 0; $i < $rsizw; $i++) {
$t = unpack('V*', mb_substr($temp, $i * 8, 8, self::ENCODING));
$st[$i] = [
$st[$i][0] ^ $t[2],
$st[$i][1] ^ $t[1]
];
}
self::keccakf64($st, self::KECCAK_ROUNDS);
$out = '';
for ($i = 0; $i < 25; $i++) {
$out .= $t = pack('V*', $st[$i][1], $st[$i][0]);
}
$r = mb_substr($out, 0, intval($outputlength / 8), self::ENCODING);
return $raw_output ? $r : bin2hex($r);
}
private static function keccakf32(&$st, $rounds): void {
$keccakf_rndc = [
[0x0000, 0x0000, 0x0000, 0x0001], [0x0000, 0x0000, 0x0000, 0x8082], [0x8000, 0x0000, 0x0000, 0x0808a], [0x8000, 0x0000, 0x8000, 0x8000],
[0x0000, 0x0000, 0x0000, 0x808b], [0x0000, 0x0000, 0x8000, 0x0001], [0x8000, 0x0000, 0x8000, 0x08081], [0x8000, 0x0000, 0x0000, 0x8009],
[0x0000, 0x0000, 0x0000, 0x008a], [0x0000, 0x0000, 0x0000, 0x0088], [0x0000, 0x0000, 0x8000, 0x08009], [0x0000, 0x0000, 0x8000, 0x000a],
[0x0000, 0x0000, 0x8000, 0x808b], [0x8000, 0x0000, 0x0000, 0x008b], [0x8000, 0x0000, 0x0000, 0x08089], [0x8000, 0x0000, 0x0000, 0x8003],
[0x8000, 0x0000, 0x0000, 0x8002], [0x8000, 0x0000, 0x0000, 0x0080], [0x0000, 0x0000, 0x0000, 0x0800a], [0x8000, 0x0000, 0x8000, 0x000a],
[0x8000, 0x0000, 0x8000, 0x8081], [0x8000, 0x0000, 0x0000, 0x8080], [0x0000, 0x0000, 0x8000, 0x00001], [0x8000, 0x0000, 0x8000, 0x8008]
];
$bc = [];
for ($round = 0; $round < $rounds; $round++) {
// Theta
for ($i = 0; $i < 5; $i++) {
$bc[$i] = [
$st[$i][0] ^ $st[$i + 5][0] ^ $st[$i + 10][0] ^ $st[$i + 15][0] ^ $st[$i + 20][0],
$st[$i][1] ^ $st[$i + 5][1] ^ $st[$i + 10][1] ^ $st[$i + 15][1] ^ $st[$i + 20][1],
$st[$i][2] ^ $st[$i + 5][2] ^ $st[$i + 10][2] ^ $st[$i + 15][2] ^ $st[$i + 20][2],
$st[$i][3] ^ $st[$i + 5][3] ^ $st[$i + 10][3] ^ $st[$i + 15][3] ^ $st[$i + 20][3]
];
}
for ($i = 0; $i < 5; $i++) {
$t = [
$bc[($i + 4) % 5][0] ^ ((($bc[($i + 1) % 5][0] << 1) | ($bc[($i + 1) % 5][1] >> 15)) & (0xFFFF)),
$bc[($i + 4) % 5][1] ^ ((($bc[($i + 1) % 5][1] << 1) | ($bc[($i + 1) % 5][2] >> 15)) & (0xFFFF)),
$bc[($i + 4) % 5][2] ^ ((($bc[($i + 1) % 5][2] << 1) | ($bc[($i + 1) % 5][3] >> 15)) & (0xFFFF)),
$bc[($i + 4) % 5][3] ^ ((($bc[($i + 1) % 5][3] << 1) | ($bc[($i + 1) % 5][0] >> 15)) & (0xFFFF))
];
for ($j = 0; $j < 25; $j += 5) {
$st[$j + $i] = [
$st[$j + $i][0] ^ $t[0],
$st[$j + $i][1] ^ $t[1],
$st[$j + $i][2] ^ $t[2],
$st[$j + $i][3] ^ $t[3]
];
}
}
// Rho Pi
$t = $st[1];
for ($i = 0; $i < 24; $i++) {
$j = self::$keccakf_piln[$i];
$bc[0] = $st[$j];
$n = self::$keccakf_rotc[$i] >> 4;
$m = self::$keccakf_rotc[$i] % 16;
$st[$j] = [
((($t[(0+$n) %4] << $m) | ($t[(1+$n) %4] >> (16-$m))) & (0xFFFF)),
((($t[(1+$n) %4] << $m) | ($t[(2+$n) %4] >> (16-$m))) & (0xFFFF)),
((($t[(2+$n) %4] << $m) | ($t[(3+$n) %4] >> (16-$m))) & (0xFFFF)),
((($t[(3+$n) %4] << $m) | ($t[(0+$n) %4] >> (16-$m))) & (0xFFFF))
];
$t = $bc[0];
}
// Chi
for ($j = 0; $j < 25; $j += 5) {
for ($i = 0; $i < 5; $i++) {
$bc[$i] = $st[$j + $i];
}
for ($i = 0; $i < 5; $i++) {
$st[$j + $i] = [
$st[$j + $i][0] ^ ~$bc[($i + 1) % 5][0] & $bc[($i + 2) % 5][0],
$st[$j + $i][1] ^ ~$bc[($i + 1) % 5][1] & $bc[($i + 2) % 5][1],
$st[$j + $i][2] ^ ~$bc[($i + 1) % 5][2] & $bc[($i + 2) % 5][2],
$st[$j + $i][3] ^ ~$bc[($i + 1) % 5][3] & $bc[($i + 2) % 5][3]
];
}
}
// Iota
$st[0] = [
$st[0][0] ^ $keccakf_rndc[$round][0],
$st[0][1] ^ $keccakf_rndc[$round][1],
$st[0][2] ^ $keccakf_rndc[$round][2],
$st[0][3] ^ $keccakf_rndc[$round][3]
];
}
}
private static function keccak32($in_raw, int $capacity, int $outputlength, $suffix, bool $raw_output): string {
$capacity /= 8;
$inlen = mb_strlen($in_raw, self::ENCODING);
$rsiz = 200 - 2 * $capacity;
$rsizw = $rsiz / 8;
$st = [];
for ($i = 0; $i < 25; $i++) {
$st[] = [0, 0, 0, 0];
}
for ($in_t = 0; $inlen >= $rsiz; $inlen -= $rsiz, $in_t += $rsiz) {
for ($i = 0; $i < $rsizw; $i++) {
$t = unpack('v*', mb_substr($in_raw, intval($i * 8 + $in_t), 8, self::ENCODING));
$st[$i] = [
$st[$i][0] ^ $t[4],
$st[$i][1] ^ $t[3],
$st[$i][2] ^ $t[2],
$st[$i][3] ^ $t[1]
];
}
self::keccakf32($st, self::KECCAK_ROUNDS);
}
$temp = mb_substr($in_raw, (int) $in_t, (int) $inlen, self::ENCODING);
$temp = str_pad($temp, (int) $rsiz, "\x0", STR_PAD_RIGHT);
$temp = substr_replace($temp, chr($suffix), $inlen, 1);
$temp = substr_replace($temp, chr((int) $temp[intval($rsiz - 1)] | 0x80), $rsiz - 1, 1);
for ($i = 0; $i < $rsizw; $i++) {
$t = unpack('v*', mb_substr($temp, $i * 8, 8, self::ENCODING));
$st[$i] = [
$st[$i][0] ^ $t[4],
$st[$i][1] ^ $t[3],
$st[$i][2] ^ $t[2],
$st[$i][3] ^ $t[1]
];
}
self::keccakf32($st, self::KECCAK_ROUNDS);
$out = '';
for ($i = 0; $i < 25; $i++) {
$out .= $t = pack('v*', $st[$i][3],$st[$i][2], $st[$i][1], $st[$i][0]);
}
$r = mb_substr($out, 0, intval($outputlength / 8), self::ENCODING);
return $raw_output ? $r: bin2hex($r);
}
private static function keccak($in_raw, int $capacity, int $outputlength, $suffix, bool $raw_output): string {
return self::$x64
? self::keccak64($in_raw, $capacity, $outputlength, $suffix, $raw_output)
: self::keccak32($in_raw, $capacity, $outputlength, $suffix, $raw_output);
}
public static function hash($in, int $mdlen, bool $raw_output = false): string {
if (!in_array($mdlen, [224, 256, 384, 512], true)) {
throw new Exception('Unsupported Keccak Hash output size.');
}
return self::keccak($in, $mdlen, $mdlen, self::LFSR, $raw_output);
}
public static function shake($in, int $security_level, int $outlen, bool $raw_output = false): string {
if (!in_array($security_level, [128, 256], true)) {
throw new Exception('Unsupported Keccak Shake security level.');
}
return self::keccak($in, $security_level, $outlen, 0x1f, $raw_output);
}
}
+140
View File
@@ -0,0 +1,140 @@
<?php
namespace kornrunner;
/**
*@see https://gist.github.com/Souptacular/f50128d63b5188490fa2
*/
use PHPUnit\Framework\TestCase;
class KeccakTest extends TestCase
{
private const SHORT = "52A608AB21CCDD8A4457A57EDE782176";
private const LONG = "3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F5623CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A15358F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0A3D84A2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764B2F83AADC66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43C70088B6183639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D817FC2534A52F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E085172E328807C02D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1";
private static $x64;
public static function setUpBeforeClass(): void {
parent::setUpBeforeClass();
$class = new \ReflectionClass(Keccak::class);
self::$x64 = $class->getProperty('x64');
self::$x64->setAccessible(true);
}
/**
* @dataProvider hash
*/
public function testHash($level, $tests) {
$x64_values = [true, false];
foreach ($x64_values as $x64_bit) {
self::$x64->setValue($x64_bit);
foreach($tests as $test) {
$message = $test[0];
$expected = $test[1];
$this->assertEquals($expected, Keccak::hash($message, $level));
$this->assertEquals(hex2bin($expected), Keccak::hash($message, $level, true));
}
}
}
public static function hash(): array {
return [
/**
* @see https://emn178.github.io/online-tools/keccak_512.html
*/
[512, [
['','0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e'],
['testing', '9558a7ba9ac74b33b347703ffe33f8d561d86d9fcad1cfd63225fb55dfea50a0953a0efafd6072377f4c396e806d5bda0294cba28762740d8446fee45a276e4a'],
['The quick brown fox jumps over the lazy dog', 'd135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609'],
['The quick brown fox jumps over the lazy dog.','ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760'],
[hex2bin(self::SHORT), '4b39d3da5bcdf4d9b769015995644311c14c435bf72b1009d6dd71b01a63b97cfb596418e8e42342d117e07471a8914314ba7b0e264dadf0cea381868cbd43d1'],
[hex2bin(self::LONG), '81950e7096d31d4f22e3db71cac725bf59e81af54c7ca9e6aeee71c010fc5467466312a01aa5c137cfb140646941556796f612c9351268737c7e9a2b9631d1fa']
]],
/**
* @see https://emn178.github.io/online-tools/keccak_384.html
*/
[384, [
['', '2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff'],
['testing', '1020b1c91956efe79b89c387b54de4f7a9c187c3970552f9f48c0da176f6326b7aa694795d2c9adcf2bdd20aec605588'],
['The quick brown fox jumps over the lazy dog', '283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3'],
['The quick brown fox jumps over the lazy dog.', '9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b'],
[hex2bin(self::SHORT), '18422ac1d3a1e54bad876883d2d6dd65f65c1d5f33a7125cc4c186405a12ed64ba96672eedda8c5a6331d28683f488eb'],
[hex2bin(self::LONG), '6bff1c8405a3fe594e360e3bccea1ebcd509310dc79b9e45c263783d7a5dd662c6789b18bd567dbdda1554f5bee6a860'],
[hex2bin('E35780EB9799AD4C77535D4DDB683CF33EF367715327CF4C4A58ED9CBDCDD486F669F80189D549A9364FA82A51A52654EC721BB3AAB95DCEB4A86A6AFA93826DB923517E928F33E3FBA850D45660EF83B9876ACCAFA2A9987A254B137C6E140A21691E1069413848'), '9fb5700502e01926824f46e9f61894f9487dbcf8ae6217203c85606f975566539376d6239db04aef9bf48ca4f191a90b'],
]],
/**
* @see https://emn178.github.io/online-tools/keccak_256.html
*/
[256, [
['', 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'],
['testing', '5f16f4c7f149ac4f9510d9cf8cf384038ad348b3bcdc01915f95de12df9d1b02'],
['The quick brown fox jumps over the lazy dog', '4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15'],
['The quick brown fox jumps over the lazy dog.', '578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d'],
[hex2bin(self::SHORT), '0e32defa2071f0b5ac0e6a108b842ed0f1d3249712f58ee0ddf956fe332a5f95'],
[hex2bin(self::LONG), '348fb774adc970a16b1105669442625e6adaa8257a89effdb5a802f161b862ea'],
[hex2bin('9F2FCC7C90DE090D6B87CD7E9718C1EA6CB21118FC2D5DE9F97E5DB6AC1E9C10'), '24dd2ee02482144f539f810d2caa8a7b75d0fa33657e47932122d273c3f6f6d1'],
]],
/**
* @see https://emn178.github.io/online-tools/keccak_224.html
*/
[224, [
['', 'f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd'],
['testing', '7b77b0b01d9b669ec7637ae75fd2f0ce234c8c8c835723b6715f4b59'],
['The quick brown fox jumps over the lazy dog', '310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe'],
['The quick brown fox jumps over the lazy dog.', 'c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab'],
[hex2bin(self::SHORT), '5679cd509c5120af54795cf477149641cf27b2ebb6a5f90340704e57'],
[hex2bin(self::LONG), '5af56987ea9cf11fcd0eac5ebc14b037365e9b1123e31cb2dfc7929a'],
]],
];
}
/**
* @dataProvider Shake
*/
public function testShake($level, $size, $tests)
{
$x64_values = [true, false];
foreach ($x64_values as $x64_bit) {
self::$x64->setValue($x64_bit);
foreach($tests as $test) {
$message = $test[0];
$expected = $test[1];
$this->assertEquals($expected, Keccak::shake($message, $level, $size));
$this->assertEquals(hex2bin($expected), Keccak::shake($message, $level, $size, true));
}
}
}
public static function shake(): array {
return [
[128, 256, [
['', '7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26'],
[hex2bin(self::SHORT), '3a0faca70c9d2b81d1064d429ea3b05ad27366f64985379ddd75bc73d6a83810'],
[hex2bin(self::LONG), '14236e75b9784df4f57935f945356cbe383fe513ed30286f91060759bcb0ef4b'],
['The quick brown fox jumps over the lazy dog', 'f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e'],
['The quick brown fox jumps over the lazy dof', '853f4538be0db9621a6cea659a06c1107b1f83f02b13d18297bd39d7411cf10c'],
]],
[256, 512, [
['', '46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be'],
[hex2bin(self::SHORT), '57119c4507f975ad0e9ea4f1166e5f9b590bf2671aaeb41d130d2c570bafc579b0b9ec485cc736a0a848bbc886cbaa79ffcd067ce64b3b410741ab011c544225'],
[hex2bin(self::LONG), '8a5199b4a7e133e264a86202720655894d48cff344a928cf8347f48379cef347dfc5bcffab99b27b1f89aa2735e23d30088ffa03b9edb02b9635470ab9f10389'],
]],
];
}
public function testUnsupportedHashOutputSize()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Unsupported Keccak Hash output size.');
Keccak::hash('', 225);
}
public function testUnsupportedShakeSecurityLevel()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Unsupported Keccak Shake security level.');
Keccak::shake('', 129, 256);
}
}