This PHP extension provides the ability to incrementally hash/encrypt/decrypt data using OpenSSL. More specifically, it provides init/update/final variants of the openssl_digest
, openssl_encrypt
and openssl_decrypt
PHP functions.
hash
and mcrypt
extensions already do this!
But the - OpenSSL is usually a fair bit faster
- OpenSSL can make use of hardware acceleration, which can make it even faster
So essentially, if speed isn't a concern, you don't need this extension. But chances are that you do have some care, if you need incremental processing.
Motivation
Some (non scientific) speed demonstrations, without using this extension. This script was used on a few different CPUs, executing under PHP 5.5.
(the "fingerprint" is only used to verify that the output of the functions are identical)
Intel Xeon X5650 [AES-NI support]
sha1 : fingerprint = b70c1887; speed = 142.583 MB/s
hash (sha1) : fingerprint = b70c1887; speed = 189.041 MB/s
openssl_digest (sha1) : fingerprint = b70c1887; speed = 464.987 MB/s
---
hash (sha256) : fingerprint = 5e1c25a1; speed = 92.435 MB/s
openssl_digest (sha256) : fingerprint = 5e1c25a1; speed = 136.683 MB/s
---
md5 : fingerprint = 63d0fc2b; speed = 442.284 MB/s
hash (md5) : fingerprint = 63d0fc2b; speed = 437.663 MB/s
openssl_digest (md5) : fingerprint = 63d0fc2b; speed = 511.088 MB/s
---
mcrypt_encrypt (aes) : fingerprint = 4bbb6b7d; speed = 40.412 MB/s
openssl_encrypt (aes) : fingerprint = 4bbb6b7d; speed = 546.724 MB/s
Via Nano U2250 (patched OpenSSL) [Via Padlock (h/w accel SHA and AES)]
sha1 : fingerprint = b70c1887; speed = 101.699 MB/s
hash (sha1) : fingerprint = b70c1887; speed = 108.982 MB/s
openssl_digest (sha1) : fingerprint = b70c1887; speed = 410.126 MB/s
---
hash (sha256) : fingerprint = 5e1c25a1; speed = 37.355 MB/s
openssl_digest (sha256) : fingerprint = 5e1c25a1; speed = 358.140 MB/s
---
md5 : fingerprint = 63d0fc2b; speed = 225.396 MB/s
hash (md5) : fingerprint = 63d0fc2b; speed = 214.926 MB/s
openssl_digest (md5) : fingerprint = 63d0fc2b; speed = 252.073 MB/s
---
mcrypt_encrypt (aes) : fingerprint = 4bbb6b7d; speed = 17.772 MB/s
openssl_encrypt (aes) : fingerprint = 4bbb6b7d; speed = 324.253 MB/s
Intel Core i5 3570 (in VM without AES-NI) [no h/w acceleration]
sha1 : fingerprint = b70c1887; speed = 474.349 MB/s
hash (sha1) : fingerprint = b70c1887; speed = 471.570 MB/s
openssl_digest (sha1) : fingerprint = b70c1887; speed = 803.955 MB/s
---
hash (sha256) : fingerprint = 5e1c25a1; speed = 185.468 MB/s
openssl_digest (sha256) : fingerprint = 5e1c25a1; speed = 296.122 MB/s
---
md5 : fingerprint = 63d0fc2b; speed = 687.946 MB/s
hash (md5) : fingerprint = 63d0fc2b; speed = 692.071 MB/s
openssl_digest (md5) : fingerprint = 63d0fc2b; speed = 750.116 MB/s
---
mcrypt_encrypt (aes) : fingerprint = 4bbb6b7d; speed = 129.070 MB/s
openssl_encrypt (aes) : fingerprint = 4bbb6b7d; speed = 360.646 MB/s
Installation
Note that this extension assumes that the PHP openssl extension is installed and loaded
This library should work on both PHP 5.x and PHP 7.x.
You'll need the PHP development libraries, as well as the OpenSSL dev files. On Debian, you can do a apt-get install php5-dev libssl-dev
to grab these (replace php5
with php7.0
or whatever is applicable). And of course, you'll need something to compile with, so apt-get install build-essential pkg-config
might be useful too.
Compile as shared library on Linux
Use the following commands in the directory where the files are:
phpize
./configure
make
make install
Now load the module in your php.ini (add extension=openssl_incr.so
), or use dl
Other platforms
No clue, do your own research
Functions
resource openssl_digest_init(string method)
Initialises digest hash calculation for given method, returns a hashing context to be used with openssl_digest_update
and openssl_digest_final
See also openssl_digest hash_init
bool openssl_digest_update(resource ctx, string data)
Updates digest hash context with given data, returns true
See also hash_update
string openssl_digest_final(resource ctx [, bool raw_output=false])
Returns digest hash value for given hashing context, as raw or binhex encoded string
See also hash_final
int openssl_digest_size(string method)
Returns the digest size, in bytes, of the specified method.
Example: openssl_digest_size('sha1') == 20
int openssl_digest_block_size(string method)
Returns the block size, in bytes, of the specified method.
Example: openssl_digest_size('md5') == 64
resource openssl_digest_copy(resource ctx)
Returns a copy of the digest hash context.
Example:
$a = openssl_digest_init('md5');
openssl_digest_update($a, 'the fox ');
$b = openssl_digest_copy($a);
openssl_digest_update($a, 'jumped');
openssl_digest_update($b, 'escaped');
echo openssl_digest_final($a); // == md5('the fox jumped')
echo openssl_digest_final($b); // == md5('the fox escaped')
resource openssl_encrypt_init(string method, string password [, long options=0 [, string $iv='']])
Creates and returns a encryption context for given method and key
Note: the OPENSSL_RAW_DATA
flag is ignored as base64 encoded output is not supported It is recommended that scripts still set the OPENSSL_RAW_DATA
flag in case this behaviour changes in the future
See also openssl_encrypt
string openssl_encrypt_update(resource ctx, string data)
Encrypts given data using given encryption context, returns raw string
As data may be processed in blocks, this function may return an empty string
string openssl_encrypt_final(resource ctx)
Returns any remaining data from encrypting context, and cleans everything up
resource openssl_decrypt_init(string method, string password [, long options=0 [, string $iv = '']])
Creates and returns a decryption context for given method and key
Note: the OPENSSL_RAW_DATA
flag is ignored as base64 encoded input is not supported It is recommended that scripts still set the OPENSSL_RAW_DATA
flag in case this behaviour changes in the future
See also openssl_decrypt
string openssl_decrypt_update(resource ctx, string data)
Decrypts and returns given raw data using given decryption context
string openssl_decrypt_final(resource ctx)
Returns any remaining data from decrypting context, and cleans everything up
int openssl_cipher_block_size(string method)
Returns the block size, in bytes, of the specified method.
Example: openssl_cipher_block_size('aes-256-cbc') == 16
int openssl_cipher_key_length(string method)
Returns the key length, in bytes, of the specified method.
Example: openssl_cipher_key_length('aes-256-cbc') == 32
See also openssl_cipher_iv_length (which this method somewhat complements)
int openssl_cipher_mode(string method)
Returns the block mode of the specified method. The return value will equal one (or more, if OR'd together) of the following OPENSSL_CIPH_* constants:
- OPENSSL_CIPH_STREAM_CIPHER
- OPENSSL_CIPH_ECB_MODE
- OPENSSL_CIPH_CBC_MODE
- OPENSSL_CIPH_CFB_MODE
- OPENSSL_CIPH_OFB_MODE
- OPENSSL_CIPH_CTR_MODE
- OPENSSL_CIPH_GCM_MODE
- OPENSSL_CIPH_CCM_MODE
- OPENSSL_CIPH_XTS_MODE
- OPENSSL_CIPH_WRAP_MODE
Example: openssl_cipher_mode('aes-256-cbc') == OPENSSL_CIPH_CBC_MODE
resource openssl_encrypt_copy(resource ctx)
Returns a copy of the resource.
resource openssl_decrypt_copy(resource ctx)
Returns a copy of the resource.
Example
<?php
// open input file
$fr = fopen('some_big_file', 'rb');
// we'll encrypt this file to the following output
$fw = fopen('encrypted_file', 'wb');
// generate an IV
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-128-cbc'));
// write the IV to the file so it can be decrypted later
fwrite($fw, $iv);
// initialise encryption
$enc = openssl_encrypt_init('aes-128-cbc', md5('My Password', true), 0, $iv);
// for demonstration purposes, also calculate the SHA1 hash of the input file
$hash = openssl_digest_init('sha1');
// read through the file
while(!feof($fr)) {
$buffer = fread($fr, 16384);
fwrite($fw, openssl_encrypt_update($enc, $buffer));
openssl_digest_update($hash, $buffer);
}
// push out any remaining data
fwrite($fw, openssl_encrypt_final($enc));
fclose($fr); fclose($fw);
echo "Hash of file is", openssl_digest_final($hash), "\n";