Skip to content
This repository has been archived by the owner on May 15, 2021. It is now read-only.

Commit

Permalink
✨ added keypair setters
Browse files Browse the repository at this point in the history
  • Loading branch information
codemasher committed Jan 27, 2018
1 parent 1df8eec commit ec3914d
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 40 deletions.
4 changes: 2 additions & 2 deletions src/Crypto/Box.php
Expand Up @@ -21,7 +21,7 @@ class Box extends CryptoBox{
*
* @return \chillerlan\Traits\Crypto\CryptoBoxInterface
*/
public function create(string $message, string $nonce_bin = null):CryptoBoxInterface{
public function create(string &$message, string &$nonce_bin = null):CryptoBoxInterface{
$this->checkKeypair(SODIUM_CRYPTO_BOX_SECRETKEYBYTES, SODIUM_CRYPTO_BOX_PUBLICKEYBYTES);
$message = $this->checkMessage($message);

Expand All @@ -48,7 +48,7 @@ public function create(string $message, string $nonce_bin = null):CryptoBoxInter
* @return \chillerlan\Traits\Crypto\CryptoBoxInterface
* @throws \chillerlan\Traits\Crypto\CryptoException
*/
public function open(string $box_bin, string $nonce_bin):CryptoBoxInterface{
public function open(string &$box_bin, string &$nonce_bin):CryptoBoxInterface{
$this->checkKeypair(SODIUM_CRYPTO_BOX_SECRETKEYBYTES, SODIUM_CRYPTO_BOX_PUBLICKEYBYTES);

$keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey($this->keypair->secret, $this->keypair->public);
Expand Down
4 changes: 2 additions & 2 deletions src/Crypto/BoxKeypair.php
Expand Up @@ -15,7 +15,7 @@
class BoxKeypair extends CryptoKeypair{

/** @inheritdoc */
public function create(string $seed_bin = null):CryptoKeyInterface{
public function create(string &$seed_bin = null):CryptoKeyInterface{

if($seed_bin !== null && strlen($seed_bin) !== SODIUM_CRYPTO_BOX_SEEDBYTES){
throw new CryptoException('invalid seed length');
Expand Down Expand Up @@ -44,7 +44,7 @@ public function create(string $seed_bin = null):CryptoKeyInterface{
* @return \chillerlan\Traits\Crypto\CryptoKeyInterface
* @throws \chillerlan\Traits\Crypto\CryptoException
*/
public function createFromSecret(string $secret_bin):CryptoKeyInterface{
public function createFromSecret(string &$secret_bin):CryptoKeyInterface{

if(strlen($secret_bin) !== SODIUM_CRYPTO_BOX_SECRETKEYBYTES){
throw new CryptoException('invalid secret key length');
Expand Down
2 changes: 1 addition & 1 deletion src/Crypto/CryptoBoxInterface.php
Expand Up @@ -27,6 +27,6 @@ interface CryptoBoxInterface{
*
* @return \chillerlan\Traits\Crypto\CryptoBoxInterface
*/
public function create(string $message):CryptoBoxInterface;
public function create(string &$message):CryptoBoxInterface;

}
2 changes: 1 addition & 1 deletion src/Crypto/CryptoKeyInterface.php
Expand Up @@ -24,6 +24,6 @@ interface CryptoKeyInterface{
*
* @return \chillerlan\Traits\Crypto\CryptoKeyInterface
*/
public function create(string $seed_bin = null):CryptoKeyInterface;
public function create(string &$seed_bin = null):CryptoKeyInterface;

}
61 changes: 60 additions & 1 deletion src/Crypto/CryptoTrait.php
Expand Up @@ -17,7 +17,66 @@ trait CryptoTrait{
/**
* @var \chillerlan\Traits\Crypto\CryptoKeyInterface
*/
protected $cryptoKeyInterface;
private $cryptoKeyInterface;

/**
* @param string|null $secret_hex
* @param string|null $public_hex
*
* @return $this
*/
protected function setBoxKeypair(string $secret_hex = null, string $public_hex = null){
return $this->setCryptoKeyInterface(BoxKeypair::class, $secret_hex, $public_hex);
}

/**
* @param string|null $secret_hex
* @param string|null $public_hex
*
* @return $this
*/
protected function setSignKeypair(string $secret_hex = null, string $public_hex = null){
return $this->setCryptoKeyInterface(SignKeypair::class, $secret_hex, $public_hex);
}

/**
* @param \chillerlan\Traits\Crypto\CryptoKeyInterface $keypair
*
* @return $this
*/
protected function setKeypair(CryptoKeyInterface $keypair){
unset($this->cryptoKeyInterface);

$this->cryptoKeyInterface = $keypair;

return $this;
}

/**
* @param string $type_fqcn
* @param string|null $secret_hex
* @param string|null $public_hex
*
* @return $this
*/
private function setCryptoKeyInterface(string $type_fqcn, string &$secret_hex = null, string &$public_hex = null){
unset($this->cryptoKeyInterface);

$this->cryptoKeyInterface = new $type_fqcn([
'secret' => !empty($secret_hex) ? sodium_hex2bin($secret_hex) : null,
'public' => !empty($public_hex) ? sodium_hex2bin($public_hex) : null,
]);

if($secret_hex !== null){
sodium_memzero($secret_hex);
}

if($public_hex !== null){
sodium_memzero($public_hex);
}

return $this;
}

/**
* @param string $seed_bin
Expand Down
4 changes: 2 additions & 2 deletions src/Crypto/SealedBox.php
Expand Up @@ -15,7 +15,7 @@
class SealedBox extends CryptoBox{

/** @inheritdoc */
public function create(string $message):CryptoBoxInterface{
public function create(string &$message):CryptoBoxInterface{
$this->checkKeypair(null, SODIUM_CRYPTO_BOX_PUBLICKEYBYTES);

$this->box = sodium_crypto_box_seal($this->checkMessage($message), $this->keypair->public);
Expand All @@ -26,7 +26,7 @@ public function create(string $message):CryptoBoxInterface{
}

/** @inheritdoc */
public function open(string $box_bin):CryptoBoxInterface{
public function open(string &$box_bin):CryptoBoxInterface{
$this->checkKeypair(SODIUM_CRYPTO_BOX_SECRETKEYBYTES, SODIUM_CRYPTO_BOX_PUBLICKEYBYTES);

$keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey($this->keypair->secret, $this->keypair->public);
Expand Down
4 changes: 2 additions & 2 deletions src/Crypto/SecretBox.php
Expand Up @@ -20,7 +20,7 @@ class SecretBox extends CryptoBox{
*
* @return \chillerlan\Traits\Crypto\CryptoBoxInterface
*/
public function create(string $message, string $nonce_bin = null):CryptoBoxInterface{
public function create(string &$message, string &$nonce_bin = null):CryptoBoxInterface{
$this->checkKeypair(SODIUM_CRYPTO_BOX_SECRETKEYBYTES);

$message = $this->checkMessage($message);
Expand All @@ -43,7 +43,7 @@ public function create(string $message, string $nonce_bin = null):CryptoBoxInter
* @return \chillerlan\Traits\Crypto\CryptoBoxInterface
* @throws \chillerlan\Traits\Crypto\CryptoException
*/
public function open(string $box_bin, string $nonce_bin):CryptoBoxInterface{
public function open(string &$box_bin, string &$nonce_bin):CryptoBoxInterface{
$this->checkKeypair(SODIUM_CRYPTO_BOX_SECRETKEYBYTES);

$this->message = sodium_crypto_secretbox_open($box_bin, $nonce_bin, $this->keypair->secret);
Expand Down
2 changes: 1 addition & 1 deletion src/Crypto/SignKeypair.php
Expand Up @@ -15,7 +15,7 @@
class SignKeypair extends CryptoKeypair{

/** @inheritdoc */
public function create(string $seed_bin = null):CryptoKeyInterface{
public function create(string &$seed_bin = null):CryptoKeyInterface{

if($seed_bin !== null && strlen($seed_bin) !== SODIUM_CRYPTO_SIGN_SEEDBYTES){
throw new CryptoException('invalid seed length');
Expand Down
4 changes: 2 additions & 2 deletions src/Crypto/SignedMessage.php
Expand Up @@ -15,7 +15,7 @@
class SignedMessage extends CryptoBox{

/** @inheritdoc */
public function create(string $message):CryptoBoxInterface{
public function create(string &$message):CryptoBoxInterface{
$this->checkKeypair(SODIUM_CRYPTO_SIGN_SECRETKEYBYTES);

$this->box = sodium_crypto_sign($this->checkMessage($message), $this->keypair->secret);
Expand All @@ -26,7 +26,7 @@ public function create(string $message):CryptoBoxInterface{
}

/** @inheritdoc */
public function open(string $box_bin):CryptoBoxInterface{
public function open(string &$box_bin):CryptoBoxInterface{
$this->checkKeypair(null, SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES);

$this->message = sodium_crypto_sign_open($box_bin, $this->keypair->public);
Expand Down
57 changes: 31 additions & 26 deletions tests/Crypto/CryptoTest.php
Expand Up @@ -12,29 +12,29 @@

namespace chillerlan\TraitTest\Crypto;

use chillerlan\Traits\Crypto\BoxKeypair;
use chillerlan\Traits\Crypto\CryptoKeyInterface;
use chillerlan\Traits\Crypto\CryptoTrait;
use PHPUnit\Framework\TestCase;

class CryptoTest extends TestCase{
use CryptoTrait;

public function setUp(){
if(!extension_loaded('sodium') || !function_exists('sodium_memzero')){
$this->markTestSkipped('sodium extension (PHP 7.2+) required!');
}

}

const TESTKEY = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
const TESTNONCE = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01";
const TESTKEY_BOX_SECRET_FROM_SEED = '3d94eea49c580aef816935762be049559d6d1440dede12e6a125f1841fff8e6f';
const TESTKEY_BOX_PUBLIC_FROM_SEED = '4701d08488451f545a409fb58ae3e58581ca40ac3f7f114698cd71deac73ca01';
const TESTKEY_BOX_PUBLIC_FROM_SECRET = '8f40c5adb68f25624ae5b214ea767a6ec94d829d3d7b5e1ad1ba6f3e2138285f';
const TESTKEY_SIGN_SECRET_FROM_SEED = '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8';
const TESTKEY_SIGN_PUBLIC_FROM_SEED = '03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8';
const TESTMESSAGE = 'likes are now florps';
const TESTMESSAGE = 'likes are now florps';

public function setUp(){

if(!extension_loaded('sodium') || !function_exists('sodium_memzero')){
$this->markTestSkipped('sodium extension (PHP 7.2+) required!');
}

}

public function testCreateBoxKeypair(){
$keypair = $this->createBoxKeypair();
Expand Down Expand Up @@ -105,7 +105,7 @@ public function testCreateSignKeypairInvalidSeed(){
}

public function testBox(){
$this->cryptoKeyInterface = $this->createBoxKeypair();
$this->setKeypair($this->createBoxKeypair());

$e = $this->createBox(self::TESTMESSAGE, null);
$d = $this->openBox($e->box, $e->nonce);
Expand All @@ -114,7 +114,7 @@ public function testBox(){
}

public function testBoxWithFixedNonce(){
$this->cryptoKeyInterface = $this->createBoxKeypair();
$this->setKeypair($this->createBoxKeypair());

$e = $this->createBox(self::TESTMESSAGE, $this::TESTNONCE);
$d = $this->openBox($e->box, $this::TESTNONCE);
Expand All @@ -127,33 +127,33 @@ public function testBoxWithFixedNonce(){
* @expectedExceptionMessage invalid message
*/
public function testCreateBoxInvalidMessage(){
$this->cryptoKeyInterface = $this->createBoxKeypair();

$this->createBox('', null);
$this
->setKeypair($this->createBoxKeypair())
->createBox('', null);
}

/**
* @expectedException \chillerlan\Traits\Crypto\CryptoException
* @expectedExceptionMessage invalid secret key
*/
public function testCreateBoxInvalidSecret(){
$this->cryptoKeyInterface = new BoxKeypair(['secret' => 'foo', 'public' => $this::TESTKEY]);

$this->createBox(self::TESTMESSAGE, null);
$this
->setBoxKeypair('DEADBEEF', sodium_bin2hex($this::TESTKEY))
->createBox(self::TESTMESSAGE, null);
}

/**
* @expectedException \chillerlan\Traits\Crypto\CryptoException
* @expectedExceptionMessage invalid public key
*/
public function testCreateBoxInvalidPublic(){
$this->cryptoKeyInterface = new BoxKeypair(['secret' => $this::TESTKEY, 'public' => 'foo']);

$this->createBox(self::TESTMESSAGE, null);
$this
->setBoxKeypair(sodium_bin2hex($this::TESTKEY), 'DEADBEEF')
->createBox(self::TESTMESSAGE, null);
}

public function testSecretBox(){
$this->cryptoKeyInterface = $this->createBoxKeypair();
$this->setKeypair($this->createBoxKeypair());

$e = $this->createSecretBox(self::TESTMESSAGE, null);
$d = $this->openSecretBox($e->box, $e->nonce);
Expand All @@ -162,7 +162,7 @@ public function testSecretBox(){
}

public function testSecretBoxWithFixedNonce(){
$this->cryptoKeyInterface = $this->createBoxKeypair();
$this->setKeypair($this->createBoxKeypair());

$e = $this->createSecretBox(self::TESTMESSAGE, $this::TESTNONCE);
$d = $this->openSecretBox($e->box, $this::TESTNONCE);
Expand All @@ -175,9 +175,9 @@ public function testSecretBoxWithFixedNonce(){
* @expectedExceptionMessage nonce size should be SODIUM_CRYPTO_SECRETBOX_NONCEBYTES bytes
*/
public function testCreateSecretBoxInvalidNonce(){
$this->cryptoKeyInterface = $this->createBoxKeypair();

$this->createSecretBox(self::TESTMESSAGE, 'foo');
$this
->setKeypair($this->createBoxKeypair())
->createSecretBox(self::TESTMESSAGE, 'foo');
}

public function testSealedBox(){
Expand All @@ -190,7 +190,12 @@ public function testSealedBox(){
}

public function testSignMessage(){
$this->cryptoKeyInterface = $this->createSignKeypair();
$this->setKeypair($this->createSignKeypair());

$e = $this->signMessage(self::TESTMESSAGE);
$d = $this->verifySignedMessage($e->box);

$this->setSignKeypair($this::TESTKEY_SIGN_SECRET_FROM_SEED, $this::TESTKEY_SIGN_PUBLIC_FROM_SEED);

$e = $this->signMessage(self::TESTMESSAGE);
$d = $this->verifySignedMessage($e->box);
Expand Down

0 comments on commit ec3914d

Please sign in to comment.