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

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
codemasher committed Jan 25, 2018
1 parent d732f28 commit 827150d
Show file tree
Hide file tree
Showing 14 changed files with 842 additions and 0 deletions.
63 changes: 63 additions & 0 deletions src/Crypto/Box.php
@@ -0,0 +1,63 @@
<?php
/**
* Class Box
*
* @filesource Box.php
* @created 25.01.2018
* @package chillerlan\Traits\Crypto
* @author Smiley <smiley@chillerlan.net>
* @copyright 2018 Smiley
* @license MIT
*/

namespace chillerlan\Traits\Crypto;


class Box extends CryptoBox{

/**
* @param string $message
* @param string|null $nonce_bin
*
* @return \chillerlan\Traits\Crypto\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);

$this->nonce = $nonce_bin ?? random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);

$keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey($this->keypair->secret, $this->keypair->public);

$this->box = sodium_crypto_box($message, $this->nonce, $keypair);

sodium_memzero($keypair);
sodium_memzero($message);

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

return $this;
}

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);

$this->message = sodium_crypto_box_open($box_bin, $nonce_bin, $keypair);

sodium_memzero($keypair);
sodium_memzero($box_bin);
sodium_memzero($nonce_bin);

if($this->message === false){
throw new CryptoException('invalid box');
}

return $this;
}


}
62 changes: 62 additions & 0 deletions src/Crypto/BoxKeypair.php
@@ -0,0 +1,62 @@
<?php
/**
* Class BoxKeypair
*
* @filesource BoxKeypair.php
* @created 24.01.2018
* @package chillerlan\Traits\Crypto
* @author Smiley <smiley@chillerlan.net>
* @copyright 2018 Smiley
* @license MIT
*/

namespace chillerlan\Traits\Crypto;

class BoxKeypair extends CryptoKeypair{

/** @inheritdoc */
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');
}

$keypair = $seed_bin
? sodium_crypto_box_seed_keypair($seed_bin)
: sodium_crypto_box_keypair();

$this->keypair = $keypair;
$this->secret = sodium_crypto_box_secretkey($keypair);
$this->public = sodium_crypto_box_publickey($keypair);

sodium_memzero($keypair);

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

return $this;
}

/**
* @param string $secret_bin
*
* @return \chillerlan\Traits\Crypto\CryptoKeyInterface
* @throws \chillerlan\Traits\Crypto\CryptoException
*/
public function createFromSecret(string $secret_bin):CryptoKeyInterface{

if(strlen($secret_bin) !== SODIUM_CRYPTO_BOX_SECRETKEYBYTES){
throw new CryptoException('invalid secret key length');
}

$this->secret = $secret_bin;
$this->public = sodium_crypto_box_publickey_from_secretkey($this->secret);
$this->keypair = $this->secret.$this->secret;

sodium_memzero($secret_bin);

return $this;
}

}
99 changes: 99 additions & 0 deletions src/Crypto/CryptoBox.php
@@ -0,0 +1,99 @@
<?php
/**
* Class CryptoBox
*
* @filesource CryptoBox.php
* @created 25.01.2018
* @package chillerlan\Traits\Crypto
* @author Smiley <smiley@chillerlan.net>
* @copyright 2018 Smiley
* @license MIT
*/

namespace chillerlan\Traits\Crypto;

use chillerlan\Traits\{
Container, ContainerInterface
};

/**
* @link https://paragonie.com/book/pecl-libsodium/read/00-intro.md
* @link https://paragonie.com/book/pecl-libsodium/read/01-quick-start.md
*/
abstract class CryptoBox implements CryptoBoxInterface, ContainerInterface{
use MemzeroDestructorTrait, Container{
__construct as containerConstruct;
}

/**
* @var \chillerlan\Traits\Crypto\CryptoKeyInterface
*/
protected $keypair;

/**
* @var string
*/
protected $box;

/**
* @var string
*/
protected $nonce;

/**
* @var string
*/
protected $message;

/** @noinspection PhpMissingParentConstructorInspection */
/**
* CryptoBox constructor.
*
* @param array|null $properties
*
* @throws \chillerlan\Traits\Crypto\CryptoException
*/
public function __construct(array $properties = null){

if(!extension_loaded('sodium') || !function_exists('sodium_memzero')){
throw new CryptoException('sodium extension (PHP 7.2+) required!'); // @codeCoverageIgnore
}

$this->containerConstruct($properties);
}

/**
* @param int $secretLength
* @param int $PublicLength
*
* @return void
* @throws \chillerlan\Traits\Crypto\CryptoException
*/
protected function checkKeypair(int $secretLength = null, int $PublicLength = null){

if($secretLength !== null){
if(!$this->keypair->secret || strlen($this->keypair->secret) !== $secretLength){
throw new CryptoException('invalid secret key');
}
}

if($PublicLength !== null){
if(!$this->keypair->public || strlen($this->keypair->public) !== $PublicLength){
throw new CryptoException('invalid public key');
}
}

}

protected function checkMessage(string $message):string {
$message = trim($message);

if(strlen($message) < 1){
throw new CryptoException('invalid message');
}

// @todo: padding?
return $message;
}

}
32 changes: 32 additions & 0 deletions src/Crypto/CryptoBoxInterface.php
@@ -0,0 +1,32 @@
<?php
/**
* Interface CryptoBoxInterface
*
* @filesource CryptoBoxInterface.php
* @created 24.01.2018
* @package chillerlan\Traits\Crypto
* @author Smiley <smiley@chillerlan.net>
* @copyright 2018 Smiley
* @license MIT
*/

namespace chillerlan\Traits\Crypto;

/**
* @property \chillerlan\Traits\Crypto\CryptoKeyInterface $keypair
* @property string $box
* @property string $nonce
* @property string $message
*
* @method \chillerlan\Traits\Crypto\CryptoBoxInterface open(string $box_bin, string $nonce_bin)
*/
interface CryptoBoxInterface{

/**
* @param string $message
*
* @return \chillerlan\Traits\Crypto\CryptoBoxInterface
*/
public function create(string $message):CryptoBoxInterface;

}
17 changes: 17 additions & 0 deletions src/Crypto/CryptoException.php
@@ -0,0 +1,17 @@
<?php
/**
* Class CryptoException
*
* @filesource CryptoException.php
* @created 24.01.2018
* @package chillerlan\Traits\Crypto
* @author Smiley <smiley@chillerlan.net>
* @copyright 2018 Smiley
* @license MIT
*/

namespace chillerlan\Traits\Crypto;

use chillerlan\Traits\TraitException;

class CryptoException extends TraitException{}
29 changes: 29 additions & 0 deletions src/Crypto/CryptoKeyInterface.php
@@ -0,0 +1,29 @@
<?php
/**
* Interface CryptoKeyInterface
*
* @filesource CryptoKeyInterface.php
* @created 24.01.2018
* @package chillerlan\Traits\Crypto
* @author Smiley <smiley@chillerlan.net>
* @copyright 2018 Smiley
* @license MIT
*/

namespace chillerlan\Traits\Crypto;

/**
* @property string $keypair
* @property string $secret
* @property string $public
*/
interface CryptoKeyInterface{

/**
* @param string|null $seed_bin
*
* @return \chillerlan\Traits\Crypto\CryptoKeyInterface
*/
public function create(string $seed_bin = null):CryptoKeyInterface;

}
58 changes: 58 additions & 0 deletions src/Crypto/CryptoKeypair.php
@@ -0,0 +1,58 @@
<?php
/**
* Class CryptoKeypair
*
* @filesource CryptoKeypair.php
* @created 24.01.2018
* @package chillerlan\Traits\Crypto
* @author Smiley <smiley@chillerlan.net>
* @copyright 2018 Smiley
* @license MIT
*/

namespace chillerlan\Traits\Crypto;

use chillerlan\Traits\{Container, ContainerInterface};

/**
* @link https://paragonie.com/book/pecl-libsodium/read/00-intro.md
* @link https://paragonie.com/book/pecl-libsodium/read/01-quick-start.md
*/
abstract class CryptoKeypair implements CryptoKeyInterface, ContainerInterface{
use MemzeroDestructorTrait, Container{
__construct as containerConstruct;
}

/**
* @var string
*/
protected $keypair;

/**
* @var string
*/
protected $secret;

/**
* @var string
*/
protected $public;

/** @noinspection PhpMissingParentConstructorInspection */
/**
* CryptoKeypair constructor.
*
* @param array|null $properties
*
* @throws \chillerlan\Traits\Crypto\CryptoException
*/
public function __construct(array $properties = null){

if(!extension_loaded('sodium') || !function_exists('sodium_memzero')){
throw new CryptoException('sodium extension (PHP 7.2+) required!'); // @codeCoverageIgnore
}

$this->containerConstruct($properties);
}

}

0 comments on commit 827150d

Please sign in to comment.