12 class Crypto extends \php_user_filter
20 public function onCreate()
22 if (!isset($this->params[
'algorithm']) ||
23 !is_object($this->params[
'algorithm']) ||
24 !($this->params[
'algorithm'] instanceof
CipherEnum)) {
25 throw new \InvalidArgumentException(
'Invalid algorithm');
28 if (!isset($this->params[
'mode']) ||
29 !is_object($this->params[
'mode']) ||
30 !($this->params[
'mode'] instanceof
ModeEnum)) {
31 throw new \InvalidArgumentException(
'Invalid mode');
34 if (!isset($this->params[
'key']) || !is_string($this->params[
'key'])) {
35 throw new \InvalidArgumentException(
'Missing or invalid key');
38 $padding = new \fpoirotte\Cryptal\Padding\None();
39 if (isset($this->params[
'padding'])) {
40 $padding = $this->params[
'padding'];
43 throw new \InvalidArgumentException(
'Invalid padding scheme');
46 $tagLength = CryptoInterface::DEFAULT_TAG_LENGTH;
47 if (isset($this->params[
'tagLength'])) {
48 $tagLength = $this->params[
'tagLength'];
50 if (!is_integer($tagLength) || $tagLength < 0) {
51 throw new \InvalidArgumentException(
'Invalid tag length');
54 $iv = isset($this->params[
'iv']) ? $this->params[
'iv'] :
'';
55 if (!is_string($iv)) {
56 throw new \InvalidArgumentException(
'Invalid initialization vector');
60 if (!isset($this->params[
'mode'])) {
61 throw new \InvalidArgumentException(
'No mode specified');
63 $mode =
"\\fpoirotte\\Cryptal\\Modes\\" . substr($this->params[
'mode'], strlen(
'MODE_'));
64 $interfaces = class_implements($mode,
true);
65 if (!$interfaces || !in_array(
"fpoirotte\Cryptal\SymmetricModeInterface", $interfaces)) {
66 throw new \InvalidArgumentException(
'Unsupported mode');
69 $allowUnsafe = isset($this->params[
'allowUnsafe']) ? (bool) $this->params[
'allowUnsafe'] :
false;
70 $cipher = Registry::buildCipher(
71 $this->params[
'algorithm'],
80 $this->blockSize = $cipher->getBlockSize();
81 $this->padding = $padding;
82 $this->mode =
new $mode(
88 $this->method =
'decrypt';
90 $this->method =
'encrypt';
95 public function filter($in, $out, &$consumed, $closing)
98 $method = $this->method;
99 # $options = stream_context_get_options($this->stream); 102 $bucket = stream_bucket_make_writeable($in);
104 $this->buffer .= $bucket->data;
105 } elseif (
'cryptal.encrypt' === $this->filtername && $closing) {
107 $missing = $this->blockSize - (strlen($this->buffer) % $this->blockSize);
108 $this->buffer .= $this->padding->getPaddingData($this->blockSize, $missing);
111 $available = strlen($this->buffer);
112 $nbBlocks = ($available - ($available % $this->blockSize)) / $this->blockSize;
115 $consume = $nbBlocks * $this->blockSize;
117 for ($i = 0; $i < $nbBlocks; $i++) {
118 $outBuffer .= $this->mode->$method(
119 substr($this->buffer, $this->blockSize * $i, $this->blockSize),
124 if (!$bucket &&
'cryptal.decrypt' === $this->filtername && $closing) {
126 $padLen = $this->padding->getPaddingSize($outBuffer, $this->blockSize);
128 $outBuffer = (string) substr($outBuffer, 0, -$padLen);
132 stream_bucket_append($out, stream_bucket_new($this->stream, $outBuffer));
133 $this->buffer = (string) substr($this->buffer, $consume);
134 $consumed += $consume;