mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 16:38:54 +00:00

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@348383 c90b9560-bf6c-de11-be94-00142212c4b1
698 lines
24 KiB
XML
698 lines
24 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<appendix xml:id="filters" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<title>List of Available Filters</title>
|
|
<para>
|
|
The following is a list of a few built-in stream filters for
|
|
use with <function>stream_filter_append</function>.
|
|
Your version of PHP may have more filters (or fewer) than those
|
|
listed here.
|
|
</para>
|
|
|
|
<para>
|
|
It is worth noting a slight asymmetry between
|
|
<function>stream_filter_append</function>
|
|
and <function>stream_filter_prepend</function>.
|
|
Every PHP stream contains a small <emphasis>read buffer</emphasis>
|
|
where it stores blocks of data retrieved from the
|
|
filesystem or other resource in order to process data
|
|
in the most efficient manner. As soon as data is pulled
|
|
from the resource into the stream's internal buffer, it
|
|
is immediately processed through any attached filters whether
|
|
the PHP application is actually ready for the data or not.
|
|
If data is sitting in the read buffer when a filter is
|
|
<emphasis>appended</emphasis>, this data will be immediately
|
|
processed through that filter making the fact that it was
|
|
sitting in the buffer seem transparent. However, if data is
|
|
sitting in the read buffer when a filter is
|
|
<emphasis>prepended</emphasis>, this data will <emphasis>NOT</emphasis>
|
|
be processed through that filter. It will instead wait until
|
|
the next block of data is retrieved from the resource.
|
|
</para>
|
|
|
|
<para>
|
|
For a list of filters installed in your version of
|
|
PHP use <function>stream_get_filters</function>.
|
|
</para>
|
|
|
|
<section xml:id="filters.string">
|
|
<title>String Filters</title>
|
|
|
|
<simpara>
|
|
Each of these filters does precisely what their name implies and
|
|
correspond to the behavior of a built-in php string handling function.
|
|
For more information on a given filter, refer to the manual page for
|
|
the corresponding function.
|
|
</simpara>
|
|
|
|
<section xml:id="filters.string.rot13">
|
|
<title>string.rot13</title>
|
|
<simpara>
|
|
Use of this filter is equivalent to processing all stream data through
|
|
the <function>str_rot13</function> function.
|
|
</simpara>
|
|
<example>
|
|
<title>string.rot13</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'string.rot13');
|
|
fwrite($fp, "This is a test.\n");
|
|
/* Outputs: Guvf vf n grfg. */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section xml:id="filters.string.toupper">
|
|
<title>string.toupper</title>
|
|
<simpara>
|
|
Use of this filter is equivalent to processing all stream data through
|
|
the <function>strtoupper</function> function.
|
|
</simpara>
|
|
<example>
|
|
<title>string.toupper</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'string.toupper');
|
|
fwrite($fp, "This is a test.\n");
|
|
/* Outputs: THIS IS A TEST. */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section xml:id="filters.string.tolower">
|
|
<title>string.tolower</title>
|
|
<simpara>
|
|
Use of this filter is equivalent to processing all stream data through
|
|
the <function>strtolower</function> function.
|
|
</simpara>
|
|
<example>
|
|
<title>string.tolower</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'string.tolower');
|
|
fwrite($fp, "This is a test.\n");
|
|
/* Outputs: this is a test. */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section xml:id="filters.string.strip_tags">
|
|
<title>string.strip_tags</title>
|
|
<simpara>
|
|
Use of this filter is equivalent to processing all stream data through
|
|
the <function>strip_tags</function> function.
|
|
It accepts parameters in one of two forms:
|
|
Either as a string containing a list of tags similar to the
|
|
second parameter of the <function>strip_tags</function> function,
|
|
or as an array of tag names.
|
|
</simpara>
|
|
<para>
|
|
&warn.deprecated.feature-7-3-0;
|
|
</para>
|
|
<example>
|
|
<title>string.strip_tags</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, "<b><i><u>");
|
|
fwrite($fp, "<b>bolded text</b> enlarged to a <h1>level 1 heading</h1>\n");
|
|
fclose($fp);
|
|
/* Outputs: <b>bolded text</b> enlarged to a level 1 heading */
|
|
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, array('b','i','u'));
|
|
fwrite($fp, "<b>bolded text</b> enlarged to a <h1>level 1 heading</h1>\n");
|
|
fclose($fp);
|
|
/* Outputs: <b>bolded text</b> enlarged to a level 1 heading */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
</section>
|
|
|
|
<section xml:id="filters.convert">
|
|
<title>Conversion Filters</title>
|
|
|
|
<simpara>
|
|
Like the string.* filters, the convert.* filters perform actions
|
|
similar to their names.
|
|
For more information on a given filter, refer to the manual page for
|
|
the corresponding function.
|
|
</simpara>
|
|
|
|
<section xml:id="filters.convert.base64">
|
|
<title>convert.base64-encode and convert.base64-decode</title>
|
|
<simpara>
|
|
Use of these filters are equivalent to processing all stream data through
|
|
the <function>base64_encode</function> and <function>base64_decode</function>
|
|
functions respectively.
|
|
<literal>convert.base64-encode</literal> supports parameters given as
|
|
an associative array. If <parameter>line-length</parameter> is given, the
|
|
base64 output will be split into chunks of <parameter>line-length</parameter>
|
|
characters each. If <parameter>line-break-chars</parameter> is given, each
|
|
chunk will be delimited by the characters given. These parameters give the
|
|
same effect as using <function>base64_encode</function> with
|
|
<function>chunk_split</function>.
|
|
</simpara>
|
|
<example>
|
|
<title>
|
|
convert.base64-encode &
|
|
convert.base64-decode
|
|
</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'convert.base64-encode');
|
|
fwrite($fp, "This is a test.\n");
|
|
fclose($fp);
|
|
/* Outputs: VGhpcyBpcyBhIHRlc3QuCg== */
|
|
|
|
$param = array('line-length' => 8, 'line-break-chars' => "\r\n");
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'convert.base64-encode', STREAM_FILTER_WRITE, $param);
|
|
fwrite($fp, "This is a test.\n");
|
|
fclose($fp);
|
|
/* Outputs: VGhpcyBp
|
|
: cyBhIHRl
|
|
: c3QuCg== */
|
|
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'convert.base64-decode');
|
|
fwrite($fp, "VGhpcyBpcyBhIHRlc3QuCg==");
|
|
fclose($fp);
|
|
/* Outputs: This is a test. */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section xml:id="filters.covert.quoted-printable">
|
|
<title>convert.quoted-printable-encode and convert.quoted-printable-decode</title>
|
|
<simpara>
|
|
Use of the decode version of this filter is equivalent to processing all stream
|
|
data through the <function>quoted_printable_decode</function> functions.
|
|
There is no function equivalent to <literal>convert.quoted-printable-encode</literal>.
|
|
<literal>convert.quoted-printable-encode</literal> supports parameters given as
|
|
an associative array. In addition to the parameters supported by
|
|
<literal>convert.base64-encode</literal>, <literal>convert.quoted-printable-encode</literal>
|
|
also supports boolean arguments <parameter>binary</parameter> and
|
|
<parameter>force-encode-first</parameter>.
|
|
<literal>convert.base64-decode</literal> only supports the
|
|
<parameter>line-break-chars</parameter> parameter as a type-hint
|
|
for stripping from the encoded payload.
|
|
</simpara>
|
|
<example>
|
|
<title>
|
|
convert.quoted-printable-encode &
|
|
convert.quoted-printable-decode
|
|
</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'convert.quoted-printable-encode');
|
|
fwrite($fp, "This is a test.\n");
|
|
/* Outputs: =This is a test.=0A */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section xml:id="filters.convert.iconv">
|
|
<title>convert.iconv.*</title>
|
|
<simpara>
|
|
The <literal>convert.iconv.*</literal> filters are available, if
|
|
<link linkend="book.iconv">iconv</link> support is enabled, and their use is
|
|
equivalent to processing all stream data with <function>iconv</function>.
|
|
These filters do not support parameters, but instead expect the input and
|
|
output encodings to be given as part of the filter name, i.e. either as
|
|
<literal>convert.iconv.<input-encoding>.<output-encoding></literal> or
|
|
<literal>convert.iconv.<input-encoding>/<output-encoding></literal>
|
|
(both notations are semantically equivalent).
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>convert.iconv.*</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$fp = fopen('php://output', 'w');
|
|
stream_filter_append($fp, 'convert.iconv.utf-16le.utf-8');
|
|
fwrite($fp, "T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.\0\n\0");
|
|
fclose($fp);
|
|
/* Outputs: This is a test. */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
</section>
|
|
|
|
<section xml:id="filters.compression">
|
|
<title>Compression Filters</title>
|
|
|
|
<simpara>
|
|
While the <link linkend="wrappers.compression">Compression Wrappers</link>
|
|
provide a way of creating
|
|
gzip and bz2 compatible files on the local filesystem, they do not provide a
|
|
means for generalized compression over network streams, nor do they provide a
|
|
means to begin with a non-compressed stream and transition to a compressed one.
|
|
For this, a compression filter may be applied to any stream resource at any time.
|
|
</simpara>
|
|
|
|
<note>
|
|
<simpara>
|
|
Compression filters do <emphasis>not</emphasis> generate headers and trailers
|
|
used by command line utilities such as <literal>gzip</literal>. They only compress
|
|
and decompress the payload portions of compressed data streams.
|
|
</simpara>
|
|
</note>
|
|
|
|
<section xml:id="filters.compression.zlib">
|
|
<title>zlib.deflate and zlib.inflate</title>
|
|
<simpara>
|
|
<literal>zlib.deflate</literal> (compression) and
|
|
<literal>zlib.inflate</literal> (decompression) are implementations of
|
|
the compression methods described in <link xlink:href="&url.rfc;1951">RFC 1951</link>.
|
|
The <literal>deflate</literal> filter takes up to three parameters passed as
|
|
an associative array.
|
|
|
|
<parameter>level</parameter> describes the compression
|
|
strength to use (1-9). Higher numbers will generally yield smaller payloads at
|
|
the cost of additional processing time. Two special compression levels also exist:
|
|
0 (for no compression at all), and -1 (zlib internal default -- currently 6).
|
|
|
|
<parameter>window</parameter> is the base-2 log of the compression loopback window size.
|
|
Higher values (up to 15 -- 32768 bytes) yield better compression at a cost of memory,
|
|
while lower values (down to 9 -- 512 bytes) yield worse compression in a smaller memory footprint.
|
|
Default <parameter>window</parameter> size is currently <constant>15</constant>.
|
|
|
|
<parameter>memory</parameter> is a scale indicating how much work memory should be allocated.
|
|
Valid values range from 1 (minimal allocation) to 9 (maximum allocation). This memory allocation
|
|
affects speed only and does not impact the size of the generated payload.
|
|
</simpara>
|
|
|
|
<note>
|
|
<simpara>
|
|
Because compression level is the most commonly used parameter, it may be alternatively
|
|
provided as a simple integer value (rather than an array element).
|
|
</simpara>
|
|
</note>
|
|
|
|
<simpara>
|
|
zlib.* compression filters are available with PHP as of version <literal>5.1.0</literal> if
|
|
<link linkend="ref.zlib">zlib</link> support is enabled. They are also available as a backport in version
|
|
<literal>5.0.x</literal> by installing the <link xlink:href="&url.pecl.package;zlib_filter">zlib_filter</link>
|
|
package from <link xlink:href="&url.pecl;">PECL</link>.
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>
|
|
<literal>zlib.deflate</literal> and
|
|
<literal>zlib.inflate</literal>
|
|
</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$params = array('level' => 6, 'window' => 15, 'memory' => 9);
|
|
|
|
$original_text = "This is a test.\nThis is only a test.\nThis is not an important string.\n";
|
|
echo "The original text is " . strlen($original_text) . " characters long.\n";
|
|
|
|
$fp = fopen('test.deflated', 'w');
|
|
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, $params);
|
|
fwrite($fp, $original_text);
|
|
fclose($fp);
|
|
|
|
echo "The compressed file is " . filesize('test.deflated') . " bytes long.\n";
|
|
echo "The original text was:\n";
|
|
/* Use readfile and zlib.inflate to decompress on the fly */
|
|
readfile('php://filter/zlib.inflate/resource=test.deflated');
|
|
|
|
/* Generates output:
|
|
|
|
The original text is 70 characters long.
|
|
The compressed file is 56 bytes long.
|
|
The original text was:
|
|
This is a test.
|
|
This is only a test.
|
|
This is not an important string.
|
|
|
|
*/
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<example>
|
|
<title>
|
|
<literal>zlib.deflate</literal> simple
|
|
</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$original_text = "This is a test.\nThis is only a test.\nThis is not an important string.\n";
|
|
echo "The original text is " . strlen($original_text) . " characters long.\n";
|
|
|
|
$fp = fopen('test.deflated', 'w');
|
|
/* Here "6" indicates compression level 6 */
|
|
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, 6);
|
|
fwrite($fp, $original_text);
|
|
fclose($fp);
|
|
|
|
echo "The compressed file is " . filesize('test.deflated') . " bytes long.\n";
|
|
|
|
/* Generates output:
|
|
|
|
The original text is 70 characters long.
|
|
The compressed file is 56 bytes long.
|
|
|
|
*/
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section xml:id="filters.compression.bzip2">
|
|
<title>bzip2.compress and bzip2.decompress</title>
|
|
<simpara>
|
|
<literal>bzip2.compress</literal> and
|
|
<literal>bzip2.decompress</literal>
|
|
work in the same manner as the zlib filters described above.
|
|
|
|
The <literal>bzip2.compress</literal> filter accepts up to two parameters given as
|
|
elements of an associative array:
|
|
|
|
<parameter>blocks</parameter> is an integer value
|
|
from 1 to 9 specifying the number of 100kbyte blocks of memory to allocate for
|
|
workspace.
|
|
|
|
<parameter>work</parameter> is also an integer value ranging from
|
|
0 to 250 indicating how much effort to expend using the normal compression method
|
|
before falling back on a slower, but more reliable method. Tuning this parameter
|
|
effects only compression speed. Neither size of compressed output nor memory usage
|
|
are changed by this setting. A work factor of 0 instructs the bzip library to use
|
|
an internal default.
|
|
|
|
The <literal>bzip2.decompress</literal> filter only accepts one parameter,
|
|
which can be passed as either an ordinary boolean value, or as the
|
|
<parameter>small</parameter> element of an associative array.
|
|
|
|
<parameter>small</parameter>, when set to a &true; value, instructs the bzip library
|
|
to perform decompression in a minimal memory footprint at the cost of speed.
|
|
</simpara>
|
|
|
|
<simpara>
|
|
bzip2.* compression filters are available with PHP as of version <literal>5.1.0</literal> if
|
|
<link linkend="ref.bzip2">bz2</link> support is enabled. They are also available as a backport in version
|
|
<literal>5.0.x</literal> by installing the <link xlink:href="&url.pecl.package;bz2_filter">bz2_filter</link>
|
|
package from <link xlink:href="&url.pecl;">PECL</link>.
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>
|
|
<literal>bzip2.compress</literal> and
|
|
<literal>bzip2.decompress</literal>
|
|
</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$param = array('blocks' => 9, 'work' => 0);
|
|
|
|
echo "The original file is " . filesize('LICENSE') . " bytes long.\n";
|
|
|
|
$fp = fopen('LICENSE.compressed', 'w');
|
|
stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param);
|
|
fwrite($fp, file_get_contents('LICENSE'));
|
|
fclose($fp);
|
|
|
|
echo "The compressed file is " . filesize('LICENSE.compressed') . " bytes long.\n";
|
|
|
|
/* Generates output:
|
|
|
|
The original text is 3288 characters long.
|
|
The compressed file is 1488 bytes long.
|
|
|
|
*/
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
</section>
|
|
|
|
<section xml:id="filters.encryption">
|
|
<title>Encryption Filters</title>
|
|
|
|
<para>
|
|
Encryption filters are especially useful for file/stream encryption.
|
|
</para>
|
|
|
|
<section xml:id="filters.encryption.mcrypt">
|
|
<title>mcrypt.* and mdecrypt.*</title>
|
|
<para>
|
|
&warn.deprecated.feature-7-1-0;
|
|
</para>
|
|
|
|
<simpara>
|
|
<literal>mcrypt.*</literal> and <literal>mdecrypt.*</literal>
|
|
provide symmetric encryption and decryption using libmcrypt.
|
|
Both sets of filters support the same algorithms available to
|
|
<link linkend="ref.mcrypt">mcrypt extension</link> in the form of
|
|
<literal>mcrypt.ciphername</literal> where <parameter>ciphername</parameter>
|
|
is the name of the cipher as it would be passed to
|
|
<function>mcrypt_module_open</function>.
|
|
The following five filter parameters are also available:
|
|
</simpara>
|
|
|
|
<para>
|
|
<table>
|
|
<title>mcrypt filter parameters</title>
|
|
<tgroup cols="4">
|
|
<thead>
|
|
<row>
|
|
<entry>Parameter</entry>
|
|
<entry>Required?</entry>
|
|
<entry>Default</entry>
|
|
<entry>Sample Values</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>mode</entry>
|
|
<entry>Optional</entry>
|
|
<entry>cbc</entry>
|
|
<entry>cbc, cfb, ecb, nofb, ofb, stream</entry>
|
|
</row>
|
|
<row>
|
|
<entry>algorithms_dir</entry>
|
|
<entry>Optional</entry>
|
|
<entry>ini_get('mcrypt.algorithms_dir')</entry>
|
|
<entry>Location of algorithms modules</entry>
|
|
</row>
|
|
<row>
|
|
<entry>modes_dir</entry>
|
|
<entry>Optional</entry>
|
|
<entry>ini_get('mcrypt.modes_dir')</entry>
|
|
<entry>Location of modes modules</entry>
|
|
</row>
|
|
<row>
|
|
<entry>iv</entry>
|
|
<entry>Required</entry>
|
|
<entry>N/A</entry>
|
|
<entry>Typically 8, 16, or 32 bytes of binary data. Depends on cipher</entry>
|
|
</row>
|
|
<row>
|
|
<entry>key</entry>
|
|
<entry>Required</entry>
|
|
<entry>N/A</entry>
|
|
<entry>Typically 8, 16, or 32 bytes of binary data. Depends on cipher</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</para>
|
|
|
|
<example>
|
|
<title>Encrypt/Decrypt with Blowfish</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
//$key assumed to be previously generated
|
|
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
|
|
$iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
|
|
$fp = fopen('encrypted-file.enc', 'wb');
|
|
fwrite($fp, $iv);
|
|
$opts = array('mode'=>'cbc','iv'=>$iv, 'key'=>$key);
|
|
stream_filter_append($fp, 'mcrypt.blowfish', STREAM_FILTER_WRITE, $opts);
|
|
fwrite($fp, 'message to encrypt');
|
|
fclose($fp);
|
|
|
|
//decrypt...
|
|
$fp = fopen('encrypted-file.enc', 'rb');
|
|
$iv = fread($fp, $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC));
|
|
$opts = array('mode'=>'cbc','iv'=>$iv, 'key'=>$key)
|
|
stream_filter_append($fp, 'mdecrypt.blowfish', STREAM_FILTER_READ, $opts);
|
|
$data = rtrim(stream_get_contents($fp));//trims off null padding
|
|
fclose($fp);
|
|
echo $data;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<example>
|
|
<title>Encrypt file using AES-128 CBC with SHA256 HMAC in PHP 5.5+</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
AES_CBC::encryptFile($password, "plaintext.txt", "encrypted.enc");
|
|
AES_CBC::decryptFile($password, "encrypted.enc", "decrypted.txt");
|
|
|
|
class AES_CBC
|
|
{
|
|
protected static $KEY_SIZES = array('AES-128'=>16,'AES-192'=>24,'AES-256'=>32);
|
|
protected static function key_size() { return self::$KEY_SIZES['AES-128']; } //default AES-128
|
|
public static function encryptFile($password, $input_stream, $aes_filename){
|
|
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
|
|
$fin = fopen($input_stream, "rb");
|
|
$fc = fopen($aes_filename, "wb+");
|
|
if (!empty($fin) && !empty($fc)) {
|
|
fwrite($fc, str_repeat("_", 32) );//placeholder, SHA256 HMAC will go here later
|
|
fwrite($fc, $hmac_salt = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM));
|
|
fwrite($fc, $esalt = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM));
|
|
fwrite($fc, $iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM));
|
|
$ekey = hash_pbkdf2("sha256", $password, $esalt, $it=1000, self::key_size(), $raw=true);
|
|
$opts = array('mode'=>'cbc', 'iv'=>$iv, 'key'=>$ekey);
|
|
stream_filter_append($fc, 'mcrypt.rijndael-128', STREAM_FILTER_WRITE, $opts);
|
|
$infilesize = 0;
|
|
while (!feof($fin)) {
|
|
$block = fread($fin, 8192);
|
|
$infilesize+=strlen($block);
|
|
fwrite($fc, $block);
|
|
}
|
|
$block_size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
|
|
$padding = $block_size - ($infilesize % $block_size);//$padding is a number from 1-16
|
|
fwrite($fc, str_repeat(chr($padding), $padding) );//perform PKCS7 padding
|
|
fclose($fin);
|
|
fclose($fc);
|
|
$hmac_raw = self::calculate_hmac_after_32bytes($password, $hmac_salt, $aes_filename);
|
|
$fc = fopen($aes_filename, "rb+");
|
|
fwrite($fc, $hmac_raw);//overwrite placeholder
|
|
fclose($fc);
|
|
}
|
|
}
|
|
public static function decryptFile($password, $aes_filename, $out_stream) {
|
|
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
|
|
$hmac_raw = file_get_contents($aes_filename, false, NULL, 0, 32);
|
|
$hmac_salt = file_get_contents($aes_filename, false, NULL, 32, $iv_size);
|
|
$hmac_calc = self::calculate_hmac_after_32bytes($password, $hmac_salt, $aes_filename);
|
|
$fc = fopen($aes_filename, "rb");
|
|
$fout = fopen($out_stream, 'wb');
|
|
if (!empty($fout) && !empty($fc) && self::hash_equals($hmac_raw,$hmac_calc)) {
|
|
fread($fc, 32+$iv_size);//skip sha256 hmac and salt
|
|
$esalt = fread($fc, $iv_size);
|
|
$iv = fread($fc, $iv_size);
|
|
$ekey = hash_pbkdf2("sha256", $password, $esalt, $it=1000, self::key_size(), $raw=true);
|
|
$opts = array('mode'=>'cbc', 'iv'=>$iv, 'key'=>$ekey);
|
|
stream_filter_append($fc, 'mdecrypt.rijndael-128', STREAM_FILTER_READ, $opts);
|
|
while (!feof($fc)) {
|
|
$block = fread($fc, 8192);
|
|
if (feof($fc)) {
|
|
$padding = ord($block[strlen($block) - 1]);//assume PKCS7 padding
|
|
$block = substr($block, 0, 0-$padding);
|
|
}
|
|
fwrite($fout, $block);
|
|
}
|
|
fclose($fout);
|
|
fclose($fc);
|
|
}
|
|
}
|
|
private static function hash_equals($str1, $str2) {
|
|
if(strlen($str1) == strlen($str2)) {
|
|
$res = $str1 ^ $str2;
|
|
for($ret=0,$i = strlen($res) - 1; $i >= 0; $i--) $ret |= ord($res[$i]);
|
|
return !$ret;
|
|
}
|
|
return false;
|
|
}
|
|
private static function calculate_hmac_after_32bytes($password, $hsalt, $filename) {
|
|
static $init=0;
|
|
$init or $init = stream_filter_register("user-filter.skipfirst32bytes", "FileSkip32Bytes");
|
|
$stream = 'php://filter/read=user-filter.skipfirst32bytes/resource=' . $filename;
|
|
$hkey = hash_pbkdf2("sha256", $password, $hsalt, $iterations=1000, 24, $raw=true);
|
|
return hash_hmac_file('sha256', $stream, $hkey, $raw=true);
|
|
}
|
|
}
|
|
class FileSkip32Bytes extends php_user_filter
|
|
{
|
|
private $skipped=0;
|
|
function filter($in, $out, &$consumed, $closing) {
|
|
while ($bucket = stream_bucket_make_writeable($in)) {
|
|
$outlen = $bucket->datalen;
|
|
if ($this->skipped<32){
|
|
$outlen = min($bucket->datalen,32-$this->skipped);
|
|
$bucket->data = substr($bucket->data, $outlen);
|
|
$bucket->datalen = $bucket->datalen-$outlen;
|
|
$this->skipped+=$outlen;
|
|
}
|
|
$consumed += $outlen;
|
|
stream_bucket_append($out, $bucket);
|
|
}
|
|
return PSFS_PASS_ON;
|
|
}
|
|
}
|
|
class AES_128_CBC extends AES_CBC {
|
|
protected static function key_size() { return self::$KEY_SIZES['AES-128']; }
|
|
}
|
|
class AES_192_CBC extends AES_CBC {
|
|
protected static function key_size() { return self::$KEY_SIZES['AES-192']; }
|
|
}
|
|
class AES_256_CBC extends AES_CBC {
|
|
protected static function key_size() { return self::$KEY_SIZES['AES-256']; }
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
</section>
|
|
|
|
</appendix>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|