Extending Randomness Sources
Here is a simple true/false source example for defining new randomness generators via the cryptography model extension approach:
use CryptoManana\Core\Abstractions\Randomness\AbstractGenerator;
use CryptoManana\Core\Interfaces\Randomness\SeedableGeneratorInterface;
use CryptoManana\Core\StringBuilder;
class BooleanRandomness extends
AbstractGenerator implements
SeedableGeneratorInterface
{
{
protected static $seed = false;
public static function setSeed($seed = null)
{
$seed = !is_null($seed) ? $seed % 2 : time() % 2;
// Set the used seed value for history
self::$seed = $seed;
}
public function getMaxNumber()
{
return 1;
}
public function getMinNumber()
{
return 0;
}
public function getInt($from = 0, $to = null)
{
$from = ($from === null) ? 0 : $from;
$to = ($to === null) ? $this->getMaxNumber() : $to;
$this->validateIntegerRange($from, $to);
$tmp = self::$seed ? 1 : 0;
self::$seed = self::$seed ? 0 : 1;
return $tmp;
}
public function getBytes($length = 1)
{
$this->validatePositiveInteger($length);
$tmpBytes = '';
for ($i = 1; $i <= $length; $i++) {
$tmpBytes .= StringBuilder::getChr($this->getInt());
}
return $tmpBytes;
}
public function __construct()
{
parent::__construct();
if (self::$seed === false) {
self::setSeed();
}
}
}
$x = new BooleanRandomness();
$x::setSeed(10);
echo $x->getBase64() . '<br>';
echo $x->getBase64() . '<br>';
$x::setSeed(9);
echo $x->getBase64() . '<br>';
echo $x->getBase64() . '<br>';
Extending Hash Functions
Here are a few simple examples for defining new hash functions via the cryptography model extension approach:
use CryptoManana\Core\Abstractions\MessageDigestion\{
AbstractUnkeyedHashFunction,
AbstractKeyedHashFunction,
AbstractKeyMaterialDerivationFunction,
AbstractIterativeSlowDerivation,
AbstractHardwareResistantDerivation
};
use CryptoManana\Core\Interfaces\MessageDigestion\AlgorithmicCostInterface;
use CryptoManana\Core\Traits\MessageDigestion\AlgorithmicCostTrait;
class Md4 extends AbstractUnkeyedHashFunction
{
const ALGORITHM_NAME = 'md4';
}
class HmacMd4 extends AbstractKeyedHashFunction
{
const ALGORITHM_NAME = 'md4';
}
class HkdfMd4 extends AbstractKeyMaterialDerivationFunction
{
const ALGORITHM_NAME = 'md4';
const ALGORITHM_MAXIMUM_OUTPUT = 4080; // `16 * 255 = 4080`
protected $outputLength = 16;
}
class Pbkdf2Md4 extends AbstractIterativeSlowDerivation
{
const ALGORITHM_NAME = 'md4';
const ALGORITHM_MAXIMUM_OUTPUT = PHP_INT_MAX;
protected $outputLength = 16;
}
class BcryptSleepy extends
AbstractHardwareResistantDerivation implements
AlgorithmicCostInterface
{
use AlgorithmicCostTrait;
const ALGORITHM_NAME = 'bcrypt';
const ALGORITHM_MAXIMUM_OUTPUT = 72;
protected $computationalCost = PASSWORD_BCRYPT_DEFAULT_COST;
protected function fetchAlgorithmVariation()
{
return PASSWORD_BCRYPT;
}
protected function fetchAlgorithmParameters()
{
return [
'cost' => $this->computationalCost
];
}
public function hashData($data)
{
usleep(mt_rand(1, 5) * 100000);
return parent::hashData($data);
}
public function verifyHash($data, $digest)
{
usleep(mt_rand(1, 5) * 100000);
return parent::verifyHash($data, $digest);
}
}
$data = 'test';
$md4 = new Md4();
$hmac = new HmacMd4();
$hkdf = new HkdfMd4();
$pbkdf2 = new Pbkdf2Md4();
echo 'MD4: ' . ($md4->hashData($data)) . '<br>';
echo 'HMAC-MD4: ' . ($hmac->hashData($data)) . '<br>';
echo 'HKDF-MD4: ' . ($hkdf->hashData($data)) . '<br>';
echo 'PBKDF-MD4: ' . ($pbkdf2->hashData($data)) . '<br>';
$sleepy = new BcryptSleepy();
echo 'Bcrypt With Sleep: ' . ($sleepy->hashData($data)) . '<br>';
Extending Symmetric Ciphers
Here are a few simple examples for defining new symmetric systems via the cryptography model extension approach:
use CryptoManana\Core\Abstractions\MessageEncryption\AbstractStreamCipherAlgorithm;
use CryptoManana\Core\Abstractions\MessageEncryption\AbstractBlockCipherAlgorithm;
class Rot13 extends AbstractStreamCipherAlgorithm
{
const ALGORITHM_NAME = 'rot13';
const KEY_SIZE = 16;
protected $useNative = false;
/**
* Stream cipher algorithm constructor.
*/
public function __construct()
{
if (strlen($this->key) < static::KEY_SIZE) {
$this->key = str_pad(
$this->key,
static::KEY_SIZE,
"\x0",
STR_PAD_RIGHT
);
}
}
public function encryptData($plainData)
{
$this->validatePlainDataForEncryption($plainData);
$plainData = ($plainData === '') ? ' ' : $plainData;
$plainData = $plainData . strrev($this->key);
$cipherData = str_rot13($plainData);
return $this->changeOutputFormat($cipherData, true);
}
public function decryptData($cipherData)
{
$this->validateCipherDataForDecryption($cipherData);
$cipherData = $this->changeOutputFormat($cipherData, false);
$cipherData = str_rot13($cipherData);
$plainData = substr($cipherData, 0, -strlen($this->key));
return $plainData;
}
}
class Des extends AbstractBlockCipherAlgorithm
{
const ALGORITHM_NAME = 'DES';
const KEY_SIZE = 8;
const IV_SIZE = 8;
const BLOCK_SIZE = 8;
protected static $validBlockModes = [
self::CBC_MODE,
self::CFB_MODE,
self::OFB_MODE,
self::ECB_MODE
];
protected function fetchAlgorithmMethodName()
{
return static::ALGORITHM_NAME . '-' . $this->mode;
}
protected function validateBlockModeSupport($mode)
{
$methodName = static::ALGORITHM_NAME . '-' . $mode;
$supported = in_array(
strtolower($methodName),
openssl_get_cipher_methods(),
true
);
if ($supported) {
throw new \RuntimeException(
'The algorithm `' . $methodName . '`is not supported.'
);
}
}
}
$data = 'test';
$rot13 = new Rot13();
$rot13->setSecretKey('yez');
$des = new Des();
$des->setSecretKey('zzz')
->setInitializationVector('xxx');
$encrypted = $rot13->encryptData($data);
$decrypted = $rot13->decryptData($encrypted);
echo 'Data: ' . $data . '<br>';
echo 'Encrypted: ' . $encrypted . '<br>';
echo 'Decrypted: ' . $decrypted . '<br>';
$encrypted = $des->encryptData($data);
$decrypted = $des->decryptData($encrypted);
echo 'Data: ' . $data . '<br>';
echo 'Encrypted: ' . $encrypted . '<br>';
echo 'Decrypted: ' . $decrypted . '<br>';
Extending Asymmetric Ciphers
Here are a few simple examples for defining new asymmetric systems via the cryptography model extension approach:
use CryptoManana\Core\Abstractions\MessageEncryption\AbstractRsaEncryption;
use CryptoManana\Core\Abstractions\MessageEncryption\AbstractDsaSignature;
use CryptoManana\Utilities\TokenGenerator;
class Rsa512 extends AbstractRsaEncryption
{
const KEY_SIZE = 512;
}
class Dsa1536 extends AbstractDsaSignature
{
const KEY_SIZE = 1536;
}
$generator = new TokenGenerator();
$keyPair = $generator->getAsymmetricKeyPair(
Rsa512::KEY_SIZE,
$generator::RSA_KEY_PAIR_TYPE
);
$crypter = new Rsa512();
$crypter->setKeyPair($keyPair);
$data = 'testing information';
echo 'Data: ' . $data . '<br>';
$cipherData = $crypter->encryptData($data);
echo 'Cipher Data: ' . $cipherData . '<br>';
echo $data === $crypter->decryptData($cipherData) ?
'Data is decrypted successfully' : 'Wrong decryption!';
// This signature is self-signed
$keyPair = $generator->getAsymmetricKeyPair(
Dsa1536::KEY_SIZE,
$generator::DSA_KEY_PAIR_TYPE
);
$signer = new Dsa1536();
$signer->setKeyPair($keyPair);
$signature = $signer->signData($data);
echo 'Data: ' . $data . '<br>';
echo 'Signature: ' . $signature . '<br>';
if ($signer->verifyDataSignature($signature, $data)) {
echo "The signature is valid!";
} else {
echo "Invalid data or signature!";
}
Extending Cryptography Services
Here are a few simple examples for defining new cryptographic services via the cryptography model extension approach:
use CryptoManana\Core\Abstractions\Containers\AbstractCryptographicProtocol;
use CryptoManana\Core\Abstractions\Containers\AbstractRandomnessInjectable;
use CryptoManana\Core\Abstractions\MessageEncryption\AbstractBlockCipherAlgorithm;
use CryptoManana\Core\Interfaces\Containers\SymmetricEncryptionInjectableInterface;
use CryptoManana\Core\Interfaces\MessageEncryption\DataEncryptionInterface;
use CryptoManana\Core\Traits\Containers\SymmetricEncryptionInjectableTrait;
use CryptoManana\SymmetricEncryption\Aes192;
use CryptoManana\Core\StringBuilder;
class TwoPassEncryption extends
AbstractCryptographicProtocol implements
SymmetricEncryptionInjectableInterface
{
use SymmetricEncryptionInjectableTrait;
protected $symmetricCipherSource = null;
public function __construct(AbstractBlockCipherAlgorithm $cipher = null)
{
if ($cipher instanceof DataEncryptionInterface) {
$this->symmetricCipherSource = $cipher;
} else {
throw new \RuntimeException(
'No symmetric encryption service has been set.'
);
}
}
public function __destruct()
{
unset($this->symmetricCipherSource);
}
public function __clone()
{
$this->symmetricCipherSource = clone $this->symmetricCipherSource;
}
public function encryptDataTwice($plainData)
{
$cipherData = $this->symmetricCipherSource->encryptData($plainData);
return $this->symmetricCipherSource->encryptData(
StringBuilder::stringReverse($cipherData)
);
}
public function decryptDataTwice($cipherData)
{
$plainData = $this->symmetricCipherSource->decryptData($cipherData);
$plainData = StringBuilder::stringReverse($plainData);
return $this->symmetricCipherSource->decryptData($plainData);
}
}
class QuestionAnswerer extends AbstractRandomnessInjectable
{
public function askQuestion($question = '')
{
if (!is_string($question)) {
throw new \InvalidArgumentException(
'The supplied argument is not of type string.'
);
}
$answers = [
'Yes.',
'No.',
'Maybe..',
'I don\'t know!',
'Can you repeat that question?!',
'Yez?'
];
$index = $this->randomnessSource->getInt(0, count($answers) - 1);
return $answers[$index];
}
}
$symmetricCipher = new Aes192();
$symmetricCipher->setSecretKey('crypto')
->setInitializationVector('manana');
$protocol = new TwoPassEncryption($symmetricCipher);
$data = 'test information';
echo 'Original Data: ' . $data . '<br>';
$encryptedData = $protocol->encryptDataTwice($data, 7);
$decryptedData = $protocol->decryptDataTwice($encryptedData, 7);
$wrongDecrypt = $protocol->encryptDataTwice($encryptedData . 'z$13=Fя');
echo 'Encrypted Data: ' . $encryptedData . '<br>';
echo 'Decrypted Data: ' . $decryptedData . '<br>';
echo 'Wrongly Decrypted: ' . $wrongDecrypt . '<br>';
$crystalBall = new QuestionAnswerer();
$question = 'Will I get lucky tonight?';
echo 'Question: ' . $question . '<br>';
echo 'Answer: ' . $crystalBall->askQuestion($question) . '<br>';
Extending Data Structures
Here is a simple example for defining a new data structure for services via the cryptography model extension approach:
use CryptoManana\Core\Abstractions\DataStructures\AbstractBasicStructure;
class TimedData extends AbstractBasicStructure
{
protected $data = '';
protected $times = 0;
public function __construct($data = '', $times = 0)
{
$this->__set('data', $data);
$this->__set('times', $times);
}
public function __destruct()
{
}
public function __toString()
{
return 'data : ' . $this->data . ' | times : ' . $this->times;
}
}
$tmp = new TimedData();
$tmp->data = 'data';
$tmp->times = 2;
$tmp->times = []; // error
Extending Framework Exception
Here is a simple example for defining a new framework exception via the cryptography model extension approach:
use CryptoManana\Core\Abstractions\ErrorHandling\AbstractCryptologyException;
class WrongConfigurationException extends AbstractCryptologyException
{
const INTERNAL_CODE = 69;
protected $code = self::INTERNAL_CODE;
public function getFrameworkErrorCode()
{
return static::INTERNAL_CODE;
}
}
$tmp = new WrongConfigurationException();
throw $tmp->setCode(500)
->setMessage('Wrong configuration')
->setFile(__FILE__)
->setLine(__LINE__);
Extending Factories
Here is a simple example for defining a new factory via the cryptography model extension approach:
use CryptoManana\Core\Abstractions\DesignPatterns\AbstractFactory;
abstract class AbstractNumber
{
abstract public function __toString();
}
class One extends AbstractNumber
{
const NAME = '1';
public function __toString()
{
return self::NAME;
}
}
class Two extends AbstractNumber
{
const NAME = '2';
public function __toString()
{
return self::NAME;
}
}
class NumberFactory extends AbstractFactory
{
const NUMBER_ONE = One::class;
const NUMBER_TWO = Two::class;
public function __debugInfo()
{
return [
self::class . '::NUMBER_ONE' => self::NUMBER_ONE,
self::class . '::NUMBER_TWO' => self::NUMBER_TWO,
];
}
public function create($type)
{
return self::createInstance($type);
}
public static function createInstance($type)
{
if (
class_exists($type) &&
is_subclass_of($type, AbstractNumber::class)
) {
$exception = new $type();
} else {
$exception = null; // Invalid type given
}
return $exception;
}
}
$factory = new NumberFactory();
echo 'Results: ' . '<br>';
echo $factory->create($factory::NUMBER_ONE);
echo $factory::createInstance($factory::NUMBER_TWO);