<?php
declare(strict_types=1);
namespace ParagonIE\EasyECC\Curve25519;
use Mdanter\Ecc\Crypto\EcDH\EcDHInterface;
use Mdanter\Ecc\Crypto\Key\PrivateKeyInterface;
use Mdanter\Ecc\Crypto\Key\PublicKeyInterface;
use ParagonIE\EasyECC\Exception\NotImplementedException;
/**
* Class X25519
* @package ParagonIE\EasyECC\Curve25519
*/
class X25519 implements EcDHInterface
{
/** @var MontgomerySecretKey $sk */
protected $sk;
/** @var MontgomeryPublicKey $pk */
protected $pk;
/**
* X25519 constructor.
* @param PrivateKeyInterface|null $sk
* @param PublicKeyInterface|null $pk
* @throws \SodiumException
* @throws \TypeError
*/
public function __construct(PrivateKeyInterface $sk = null, PublicKeyInterface $pk = null)
{
if ($sk) {
$this->setSenderKey($sk);
}
if ($pk) {
$this->setRecipientKey($pk);
}
}
/**
* @return string
* @throws \SodiumException
* @throws \TypeError
*/
public function scalarMult(): string
{
return \ParagonIE_Sodium_Compat::crypto_scalarmult(
$this->sk->getAsString(),
$this->pk->getAsString()
);
}
/**
* @param bool $isClient
* @return string
* @throws \SodiumException
* @throws \TypeError
*/
public function keyExchange(bool $isClient): string
{
/** @var MontgomeryPublicKey $s_pk */
$s_pk = $this->sk->getPublicKey();
if ($isClient) {
return \ParagonIE_Sodium_Compat::crypto_kx_client_session_keys(
$this->sk->getAsString() . $s_pk->getAsString(),
$this->pk->getAsString()
)[0];
}
return \ParagonIE_Sodium_Compat::crypto_kx_server_session_keys(
$this->sk->getAsString() . $s_pk->getAsString(),
$this->pk->getAsString()
)[1];
}
/**
* Calculates and returns the shared key for the exchange.
*
* @return \GMP
* @throws NotImplementedException
*/
public function calculateSharedKey(): \GMP
{
throw new NotImplementedException('This is not part of the curve25519 interface');
}
/**
* @return PublicKeyInterface
* @throws NotImplementedException
*/
public function createMultiPartyKey(): PublicKeyInterface
{
throw new NotImplementedException('This is not part of the curve25519 interface');
}
/**
* Sets the sender's key.
*
* @param PrivateKeyInterface $key
* @return void
* @throws \SodiumException
* @throws \TypeError
*/
public function setSenderKey(PrivateKeyInterface $key)
{
if ($key instanceof MontgomerySecretKey) {
$this->sk = $key;
} elseif ($key instanceof EdwardsSecretKey) {
$this->sk = $key->getMontgomery();
} else {
throw new \TypeError('Only libsodium keys are allowed');
}
}
/**
* Sets the recipient key.
*
* @param PublicKeyInterface $key
* @return void
* @throws \SodiumException
* @throws \TypeError
*/
public function setRecipientKey(PublicKeyInterface $key)
{
if ($key instanceof MontgomeryPublicKey) {
$this->pk = $key;
} elseif ($key instanceof EdwardsPublicKey) {
$this->pk = $key->getMontgomery();
} else {
throw new \TypeError('Only libsodium keys are allowed');
}
}
}
|