Skip to content

Commit

Permalink
Merge pull request #2 from paragonie/defuse
Browse files Browse the repository at this point in the history
Integrate with defuse/php-encryption
  • Loading branch information
paragonie-scott authored Feb 11, 2018
2 parents 5747a2d + 7fc6a9c commit 31a874c
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 3 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"require": {
"php": "^7",
"defuse/php-encryption": "^2.1",
"mdanter/ecc": "^0.5",
"paragonie/sodium_compat": "^1",
"paragonie/constant_time_encoding": "^2.1"
Expand Down
12 changes: 9 additions & 3 deletions src/EasyECC.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,21 +95,27 @@ public function generatePrivateKey(): PrivateKeyInterface
* @param PrivateKeyInterface $private
* @param PublicKeyInterface $public
* @param bool $isClient
* @param string $hashAlgo
* @return string
* @throws \SodiumException
* @throws \TypeError
*/
public function keyExchange(
PrivateKeyInterface $private,
PublicKeyInterface $public,
bool $isClient
bool $isClient,
string $hashAlgo = ''
): string {
if ($this->curve === 'sodium') {
$ecdh = new X25519();
$ecdh->setSenderKey($private);
$ecdh->setRecipientKey($public);
return $ecdh->keyExchange($isClient);
}
if (empty($hashAlgo)) {
// Use the default
$hashAlgo = $this->hashAlgo;
}
$ss = $this->scalarMult($private, $public);
$derSer = new DerPublicKeySerializer();

Expand All @@ -118,13 +124,13 @@ public function keyExchange(

if ($isClient) {
return hash(
$this->hashAlgo,
$hashAlgo,
$ss . $sender_pk . $recip_pk,
true
);
} else {
return hash(
$this->hashAlgo,
$hashAlgo,
$ss . $recip_pk . $sender_pk,
true
);
Expand Down
133 changes: 133 additions & 0 deletions src/Integration/Defuse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php
declare(strict_types=1);
namespace ParagonIE\EasyECC\Integration;
use Defuse\Crypto\Crypto;
use Defuse\Crypto\Encoding;
use Defuse\Crypto\Exception\BadFormatException;
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
use Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException;
use Defuse\Crypto\Key;
use Mdanter\Ecc\Crypto\Key\PrivateKeyInterface;
use Mdanter\Ecc\Crypto\Key\PublicKeyInterface;
use ParagonIE\ConstantTime\Base64UrlSafe;
use ParagonIE\EasyECC\EasyECC;

/**
* Class Defuse
* @package ParagonIE\EasyECC\Integration
*/
class Defuse
{
/** @var EasyECC $ecc */
protected $ecc;

/**
* Defuse constructor.
* @param EasyECC $ecc
*/
public function __construct(EasyECC $ecc)
{
$this->ecc = $ecc;
}

/**
* @param PrivateKeyInterface $private
* @param PublicKeyInterface $public
* @param bool $isClient
* @return Key
*
* @throws \Defuse\Crypto\Exception\BadFormatException
* @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException
* @throws \SodiumException
* @throws \TypeError
*/
public function keyExchange(
PrivateKeyInterface $private,
PublicKeyInterface $public,
bool $isClient
): Key {
return Key::loadFromAsciiSafeString(
Encoding::saveBytesToChecksummedAsciiSafeString(
Key::KEY_CURRENT_VERSION,
$this->ecc->keyExchange($private, $public, $isClient, 'sha256')
)
);
}

/**
* @param string $message
* @param PrivateKeyInterface $privateKey
* @param PublicKeyInterface $publicKey
* @return string
*
* @throws EnvironmentIsBrokenException
* @throws BadFormatException
* @throws \SodiumException
* @throws \TypeError
*/
public function asymmetricEncrypt(
string $message,
PrivateKeyInterface $privateKey,
PublicKeyInterface $publicKey
): string {
return $this->symmetricEncrypt(
$message,
$this->keyExchange($privateKey, $publicKey, true)
);
}

/**
* @param string $message
* @param PrivateKeyInterface $privateKey
* @param PublicKeyInterface $publicKey
* @return string
*
* @throws EnvironmentIsBrokenException
* @throws WrongKeyOrModifiedCiphertextException
* @throws BadFormatException
* @throws \SodiumException
* @throws \TypeError
*/
public function asymmetricDecrypt(
string $message,
PrivateKeyInterface $privateKey,
PublicKeyInterface $publicKey
): string {
return $this->symmetricDecrypt(
$message,
$this->keyExchange($privateKey, $publicKey, false)
);
}

/**
* @param string $message
* @param Key $key
* @return string
*
* @throws EnvironmentIsBrokenException
*/
public function symmetricEncrypt(string $message, Key $key): string
{
return Base64UrlSafe::encode(
Crypto::encrypt($message, $key, true)
);
}

/**
* @param string $message
* @param Key $key
* @return string
*
* @throws EnvironmentIsBrokenException
* @throws WrongKeyOrModifiedCiphertextException
* @throws \TypeError
*/
public function symmetricDecrypt(string $message, Key $key): string
{
return Crypto::decrypt(
Base64UrlSafe::decode($message),
$key,
true
);
}
}
141 changes: 141 additions & 0 deletions tests/Integration/DefuseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php
declare(strict_types=1);
namespace ParagonIE\EasyECC\Tests\Integration;

use Defuse\Crypto\Exception\BadFormatException;
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
use Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException;
use ParagonIE\EasyECC\Exception\ConfigException;
use ParagonIE\EasyECC\EasyECC;
use ParagonIE\EasyECC\Integration\Defuse;
use PHPUnit\Framework\TestCase;

/**
* Class DefuseTest
* @package ParagonIE\EasyECC\Tests\Integration
*/
class DefuseTest extends TestCase
{
/** @var EasyECC $k256 */
protected $k256;

/** @var EasyECC $p256 */
protected $p256;

/** @var EasyECC $p384 */
protected $p384;

/** @var EasyECC $sodium */
protected $sodium;

/**
* @throws ConfigException
*/
public function setUp()
{
$this->k256 = new EasyECC('K256');
$this->p256 = new EasyECC('P256');
$this->p384 = new EasyECC('P384');
$this->sodium = new EasyECC();
}

/**
* @throws BadFormatException
* @throws EnvironmentIsBrokenException
* @throws WrongKeyOrModifiedCiphertextException
* @throws \SodiumException
* @throws \TypeError
*/
public function testAsymmetricEncryptK256()
{
$alice_sk = $this->k256->generatePrivateKey();
$alice_pk = $alice_sk->getPublicKey();
$bob_sk = $this->k256->generatePrivateKey();
$bob_pk = $bob_sk->getPublicKey();

$defuse = new Defuse($this->k256);

$message = 'This is a test message.';
$ciphertext = $defuse->asymmetricEncrypt($message, $alice_sk, $bob_pk);

$this->assertSame(
$message,
$defuse->asymmetricDecrypt($ciphertext, $bob_sk, $alice_pk)
);
}

/**
* @throws BadFormatException
* @throws EnvironmentIsBrokenException
* @throws WrongKeyOrModifiedCiphertextException
* @throws \SodiumException
* @throws \TypeError
*/
public function testAsymmetricEncryptP256()
{
$alice_sk = $this->p256->generatePrivateKey();
$alice_pk = $alice_sk->getPublicKey();
$bob_sk = $this->p256->generatePrivateKey();
$bob_pk = $bob_sk->getPublicKey();

$defuse = new Defuse($this->p256);

$message = 'This is a test message.';
$ciphertext = $defuse->asymmetricEncrypt($message, $alice_sk, $bob_pk);

$this->assertSame(
$message,
$defuse->asymmetricDecrypt($ciphertext, $bob_sk, $alice_pk)
);
}

/**
* @throws BadFormatException
* @throws EnvironmentIsBrokenException
* @throws WrongKeyOrModifiedCiphertextException
* @throws \SodiumException
* @throws \TypeError
*/
public function testAsymmetricEncryptP384()
{
$alice_sk = $this->p384->generatePrivateKey();
$alice_pk = $alice_sk->getPublicKey();
$bob_sk = $this->p384->generatePrivateKey();
$bob_pk = $bob_sk->getPublicKey();

$defuse = new Defuse($this->p384);

$message = 'This is a test message.';
$ciphertext = $defuse->asymmetricEncrypt($message, $alice_sk, $bob_pk);

$this->assertSame(
$message,
$defuse->asymmetricDecrypt($ciphertext, $bob_sk, $alice_pk)
);
}

/**
* @throws BadFormatException
* @throws EnvironmentIsBrokenException
* @throws WrongKeyOrModifiedCiphertextException
* @throws \SodiumException
* @throws \TypeError
*/
public function testAsymmetricEncryptSodium()
{
$alice_sk = $this->sodium->generatePrivateKey();
$alice_pk = $alice_sk->getPublicKey();
$bob_sk = $this->sodium->generatePrivateKey();
$bob_pk = $bob_sk->getPublicKey();

$defuse = new Defuse($this->sodium);

$message = 'This is a test message.';
$ciphertext = $defuse->asymmetricEncrypt($message, $alice_sk, $bob_pk);

$this->assertSame(
$message,
$defuse->asymmetricDecrypt($ciphertext, $bob_sk, $alice_pk)
);
}
}

0 comments on commit 31a874c

Please sign in to comment.