Skip to content

Commit

Permalink
Misuse-resistance Prevent mismatched public keys
Browse files Browse the repository at this point in the history
  • Loading branch information
paragonie-security committed Jun 20, 2022
1 parent 98961ef commit f048b07
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/Keys/AsymmetricSecretKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use ParagonIE\Paseto\{
Exception\ExceptionCode,
Exception\PasetoException,
Exception\SecurityException,
SendingKey,
ProtocolInterface,
Util
Expand Down Expand Up @@ -80,6 +81,23 @@ public function __construct(
$keypair = sodium_crypto_sign_seed_keypair($keyData);
$keyData = Binary::safeSubstr($keypair, 0, 64);
}

/* Misuse-resistance: Prevent mismatched public keys
*
* See: https://github.com/MystenLabs/ed25519-unsafe-libs
*/
$sk = Binary::safeSubstr(
sodium_crypto_sign_seed_keypair(
Binary::safeSubstr($keyData, 0, 32)
),
0,
64
);
if (!hash_equals($keyData, $sk)) {
throw new SecurityException(
"Key mismatch: Public key doesn't belong to private key."
);
}
}
$this->key = $keyData;
$this->protocol = $protocol;
Expand Down
33 changes: 33 additions & 0 deletions tests/KeyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
declare(strict_types=1);
namespace ParagonIE\Paseto\Tests;

use ParagonIE\ConstantTime\Binary;
use ParagonIE\Paseto\Exception\SecurityException;
use ParagonIE\Paseto\Keys\AsymmetricPublicKey;
use ParagonIE\Paseto\Keys\AsymmetricSecretKey;
use ParagonIE\Paseto\ProtocolInterface;
use ParagonIE\Paseto\Util;
use ParagonIE\Paseto\Protocol\{
Version1,
Expand Down Expand Up @@ -170,4 +173,34 @@ public function sampleKeyTrail(string $secret, string $public, string $base64):
'Re-encoding fails'
);
}

public function ed25519provider()
{
return [
[new Version2],
[new Version4],
];
}

/**
* @dataProvider ed25519provider
*/
public function testInvalidEdDSAKey(ProtocolInterface $version)
{
if (!extension_loaded('sodium')) {
$this->markTestSkipped('Slow test on sodium_compat');
}
$keypair1 = sodium_crypto_sign_keypair();
$keypair2 = sodium_crypto_sign_keypair();

$good1 = Binary::safeSubstr($keypair1, 0, 64);
$good2 = Binary::safeSubstr($keypair2, 0, 64);
$bad = Binary::safeSubstr($keypair1, 0, 32) . Binary::safeSubstr($keypair2, 32, 32);

new AsymmetricSecretKey($good1, $version);
new AsymmetricSecretKey($good2, $version);

$this->expectException(SecurityException::class);
new AsymmetricSecretKey($bad, $version);
}
}

0 comments on commit f048b07

Please sign in to comment.