-
-
Notifications
You must be signed in to change notification settings - Fork 601
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #832 from Slamdunk/hmac_blake2b
Add Blake2b signature algorithm
- Loading branch information
Showing
4 changed files
with
175 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace Lcobucci\JWT\Signer; | ||
|
||
use Lcobucci\JWT\Signer; | ||
|
||
use function hash_equals; | ||
use function sodium_crypto_generichash; | ||
use function strlen; | ||
|
||
final class Blake2b implements Signer | ||
{ | ||
private const MINIMUM_KEY_LENGTH_IN_BITS = 256; | ||
|
||
public function algorithmId(): string | ||
{ | ||
return 'BLAKE2B'; | ||
} | ||
|
||
public function sign(string $payload, Key $key): string | ||
{ | ||
$actualKeyLength = 8 * strlen($key->contents()); | ||
|
||
if ($actualKeyLength < self::MINIMUM_KEY_LENGTH_IN_BITS) { | ||
throw InvalidKeyProvided::tooShort(self::MINIMUM_KEY_LENGTH_IN_BITS, $actualKeyLength); | ||
} | ||
|
||
return sodium_crypto_generichash($payload, $key->contents()); | ||
} | ||
|
||
public function verify(string $expected, string $payload, Key $key): bool | ||
{ | ||
return hash_equals($expected, $this->sign($payload, $key)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace Lcobucci\JWT; | ||
|
||
use Lcobucci\JWT\Signer\Blake2b; | ||
use Lcobucci\JWT\Signer\Key; | ||
use Lcobucci\JWT\Signer\Key\InMemory; | ||
use PhpBench\Benchmark\Metadata\Annotations\Groups; | ||
|
||
/** @Groups({"Hmac"}) */ | ||
final class Blake2bBench extends SignerBench | ||
{ | ||
private const ENCODED_KEY = 'b6DNRcX2SFapbICe6lXWYoOZA+JXL/dvkfWiv2hJv3Y='; | ||
|
||
protected function signer(): Signer | ||
{ | ||
return new Blake2b(); | ||
} | ||
|
||
protected function signingKey(): Key | ||
{ | ||
return $this->createKey(); | ||
} | ||
|
||
protected function verificationKey(): Key | ||
{ | ||
return $this->createKey(); | ||
} | ||
|
||
private function createKey(): Key | ||
{ | ||
return InMemory::base64Encoded(self::ENCODED_KEY); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace Lcobucci\JWT\Signer; | ||
|
||
use Lcobucci\JWT\Signer\Key\InMemory; | ||
use Lcobucci\JWT\SodiumBase64Polyfill; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
use function hash_equals; | ||
|
||
/** | ||
* @coversDefaultClass \Lcobucci\JWT\Signer\Blake2b | ||
* | ||
* @uses \Lcobucci\JWT\Signer\Key\InMemory | ||
* @uses \Lcobucci\JWT\SodiumBase64Polyfill::base642bin() | ||
*/ | ||
final class Blake2bTest extends TestCase | ||
{ | ||
private const KEY_ONE = 'GOu4rLyVCBxmxP+sbniU68ojAja5PkRdvv7vNvBCqDQ='; | ||
private const KEY_TWO = 'Pu7gywseH+R5HLIWnMll4rEg1ltjUPq/P9WwEzAsAb8='; | ||
private const CONTENTS = 'test'; | ||
private const EXPECTED_HASH_WITH_KEY_ONE = '/TG5kmkav/YGl3I9uQiv4cm1VN6Q0zPCom4G7+p74JU='; | ||
|
||
private const SHORT_KEY = 'PIBQuM5PopdMxtmTWmyvNA=='; | ||
|
||
private InMemory $keyOne; | ||
private InMemory $keyTwo; | ||
private string $expectedHashWithKeyOne; | ||
|
||
/** @before */ | ||
public function initializeKey(): void | ||
{ | ||
$this->keyOne = InMemory::base64Encoded(self::KEY_ONE); | ||
$this->keyTwo = InMemory::base64Encoded(self::KEY_TWO); | ||
$this->expectedHashWithKeyOne = SodiumBase64Polyfill::base642bin( | ||
self::EXPECTED_HASH_WITH_KEY_ONE, | ||
SodiumBase64Polyfill::SODIUM_BASE64_VARIANT_ORIGINAL | ||
); | ||
} | ||
|
||
/** | ||
* @test | ||
* | ||
* @covers ::algorithmId | ||
*/ | ||
public function algorithmIdMustBeCorrect(): void | ||
{ | ||
$signer = new Blake2b(); | ||
|
||
self::assertEquals('BLAKE2B', $signer->algorithmId()); | ||
} | ||
|
||
/** | ||
* @test | ||
* | ||
* @covers ::sign | ||
* @covers ::verify | ||
*/ | ||
public function generatedSignatureMustBeSuccessfullyVerified(): void | ||
{ | ||
$signer = new Blake2b(); | ||
|
||
self::assertTrue(hash_equals($this->expectedHashWithKeyOne, $signer->sign(self::CONTENTS, $this->keyOne))); | ||
self::assertTrue($signer->verify($this->expectedHashWithKeyOne, self::CONTENTS, $this->keyOne)); | ||
} | ||
|
||
/** | ||
* @test | ||
* | ||
* @covers ::sign | ||
* | ||
* @uses \Lcobucci\JWT\Signer\InvalidKeyProvided | ||
*/ | ||
public function signShouldRejectShortKeys(): void | ||
{ | ||
$signer = new Blake2b(); | ||
|
||
$this->expectException(InvalidKeyProvided::class); | ||
$this->expectExceptionMessage('Key provided is shorter than 256 bits, only 128 bits provided'); | ||
|
||
$signer->sign(self::CONTENTS, InMemory::base64Encoded(self::SHORT_KEY)); | ||
} | ||
|
||
/** | ||
* @test | ||
* | ||
* @covers ::sign | ||
* @covers ::verify | ||
*/ | ||
public function verifyShouldReturnFalseWhenExpectedHashWasNotCreatedWithSameInformation(): void | ||
{ | ||
$signer = new Blake2b(); | ||
|
||
self::assertFalse(hash_equals($this->expectedHashWithKeyOne, $signer->sign(self::CONTENTS, $this->keyTwo))); | ||
self::assertFalse($signer->verify($this->expectedHashWithKeyOne, self::CONTENTS, $this->keyTwo)); | ||
} | ||
} |