How to encrypt with ZF
- Posted by thomasw at 16:58:36 // //
- Announcements, File Transfer, Filter, Validate
Hy fellows,
today I finished some new components which took a long time for finishing them.
Zend Framework can, from today on, encrypt and decrypt content and complete files.
Supported are actually two extensions:
Mcrypt and OpenSSL
As both extensions provide a completly different encryption handling also the usage of this two adapters differ. But still, the encryption and decryption is really simple.
Mcrypt:
Let’s take a look at a simple example for string encryption with Mcrypt:
$filter = new Zend_Filter_Encrypt('myencryptionkey');
// Set a own vector, otherwise you must call getVector()
// and store this vector for later decryption
$filter->setVector('myvector');
$encrypted = $filter->filter('text_to_be_encoded');
print $encrypted;
Really, that’s all :-)
Ok, Mcrypt is really easy. Per default it uses the blowfish algorithm, but you can change it by giving the “algorithm” key. Also the mode, the directories and the vector to be used can be changed. You could also give a Zend_Config object as input where you have defined your encryption options. See the manual for details.
$filter = new Zend_Filter_Encrypt(array( 'key' => 'anotherencryptionkey', 'algorithm' => 'DES', ));
Decryption, is as easy as encryption and can be done with 2 or 3 lines of code:
$filter = new Zend_Filter_Decrypt('myencryptionkey');
// Set the vector with which the content was encrypted
$filter->setVector('myvector');
$decrypted = $filter->filter($encrypted);
print $decrypted;
]]>
Of course, you need key, vector, algorithm and method. Otherwise you will not be able to decrypt the given content. Also for decryption you can give these options eighter as array or as Zend_Config object or simply by calling the related setter methods.
But as you see the handling is really simple.
OpenSSL:
Now let’s take a look at OpenSSL. For OpenSSL you need to have public keys and your private key.
OpenSSL works completly different. Here you encode your content for the people from whom you received the public keys. Other people will not be able to decrypt your content.
So how does a simple example look like:
$filter = new Zend_Filter_Encrypt(
array('adapter' => 'openssl',
'private' => '/path/to/mykey/private.pem'));
// of course you can also give the public keys as array key at initiation
$filter->setPublicKey(
array('first' => '/public/key/path/first.pem',
'second' => '/public/key/path/second.pem')
->setPassphrase('mypassphrase');
$encrypted = $filter->filter('text_to_be_encoded');
$envelope = $filter->getEnvelopeKey();
print $encrypted;
// For decryption look at the Decrypt filter
As you see we are encoding our content for two people as we gave two public keys. Additionally we provided a passphrase which means that the envelope keys we have to provide for decryption will additionally be encrypted with this passphrase.
A malcious user who has stolen the keys will not be able to decrypt the conent when he does not know the passphrase. As it’s optional you can of course supress the passphrase.
There is one emminent change to the usage of Mcrypt. After we encoded our content with filter() we have to get the envelope keys. You have to give your oponent his envelope key.
getEnvelopeKey will return you an array which looks like the one we provided in setPublicKey but instead of the public keys it will hold the related envelope keys. Based on the array key you are able to seperate the right key for the right user.
Also this was quite simple. Only 4 lines of code for encryption of content with OpenSSL.
Now let’s decrypt the content:
$filter = new Zend_Filter_Decrypt(
array('adapter' => 'openssl',
'private' => '/path/to/mykey/private.pem'));
// of course you can also give the envelope keys at initiation
$filter->setEnvelopeKey(array('/key/from/encoder/first.pem',
'/key/from/encoder/second.pem');
->setPassphrase('mypassphrase');
$decrypted = $filter->filter($encrypted);
print $decrypted;
That’s it… when you have no passphrase and use only the options array you can decode with just 2 lines of code.
Encrypting files:
Until now it was simple… but now it get’s even simpler.
You need to encrypt and decrypt files ?
I also added file encryption and decryption filters which can be used with Zend_Form and Zend_File_Transfer. Easy as always:
$element = new Zend_File_Transfer_Adapter_Http();
$element->addFilter('Encrypt',
array('key' => 'myencryptionkey',
'vector' => 'myvector'));
Now all uploaded files will be encrypted.
Of course you can also use the file filter manually:
$filter = new Zend_Filter_File_Encrypt(
array('key' => 'myencryptionkey',
'vector' => 'myvector'));
$filter->filter('/path/to/myfile.ext');
Decryption works the same way.
As you can see the whole encryption and decryption API is simple and easy to use. This features will be available within the next release.
I hope you find it usefull and wish you a good work.
Greetings
Thomas Weidner
I18N Team Leader, Zend Framework
Zend Framework Advisory Board Member
Zend Certified Engineer for Zend Framework
Add comment
Fill out the form below to add your own comments

Thursday, January 15, 2009 - 10:39:40
Cool stuff, thanks for the good work.
Saturday, January 17, 2009 - 04:02:01
Nice! And all configuration driven if necessary!
Friday, March 27, 2009 - 21:01:13
Is there a way that you can specify the cipher to be MCRYPT_RIJNDAEL_256? I have MCRYPT_RIJNDAEL_256 working with straight php5 but when I try to set the algorithm to MCRYPT_RIJNDAEL_256 in the constructor it throws an error saying
The algorithm XXXXX is not supported
Any ideas?
Thanks, Shaun
Friday, March 27, 2009 - 21:09:44
The supported algorithm depends on what your installed mcrypt extension allows.
You would have to check your installed mcrypt extension, to see if it supports this algorithm.
Monday, March 30, 2009 - 18:32:49
My problem was I had MCRYPT_RIJNDAEL_256 in single quotes. took it out of quotes and everything worked just fine.
thanks!
Sunday, June 7, 2009 - 19:23:06
I used the exactly code above in 1.8.2 and I get the following error message:
File “myencryptionkey.php” does not exist or class “myencryptionkey” was not found in the file
Monday, June 8, 2009 - 11:51:05
I don’t think so… above you find 7 examples which do 7 different things. Also you note “/path/to” and “/key/from”… when you do “exactly” this your code can never work.
But a blog is the wrong place for helping with bugs. So it would be better to ask at IRC or within the ZF mailing lists.
Monday, October 19, 2009 - 23:18:47
Why doesn’t anyone specify information about what exactly type of data a vector takes? it tool me two days to figure out it’s an 8 character string or whatever. (for the default blowfish encryption type.
Monday, October 19, 2009 - 23:46:14
I need some help…
function encryptPassword($password) {
$my_salt = ‘hfjdoidsfhasoidfoi390ur2h3hwcnw39unr28030923u0923q3nc4ny982829xj3r9ngh8731092uc23oinuc9r832yicnc3u3092q3yq2p3yv23vq23nucq2n3nxoq2o3luoq2u3ocq3nroqwjr9q3umrxoqun3orvu3oun2′; // arbitrary
$my_vector = ‘12345678′; // arbitrary 8 char
$filter = new Zend_Filter_Encrypt(array(’key’ => ‘1′, ’salt’ => $my_salt, ‘vector’ => $my_vector)); // default (blowfish) + my salt + my vector
$encrypted_p = $filter->filter($password);
return $encrypted_p;
}
// encryption tests
$my_pass = ‘my name is victor’;
$safe_my_pass = encryptPassword($my_pass);
$safe_my_pass = trim(base64_encode($safe_my_pass));
echo(’<p>Encrypt test: ‘.$safe_my_pass.’</p>’);
outputs: “Encrypt test: ma84p6btUlt/xvDZDCyBAV/3b3t1gQLO”
but my decryption function doesn’t seem to work and I don’t know why… (also I am quite new to the encryption game)
// DECRYPT
$password = $safe_my_pass;
function decryptPassword($password) {
$my_salt = ‘hfjdoidsfhasoidfoi390ur2h3hwcnw39unr28030923u0923q3nc4ny982829xj3r9ngh8731092uc23oinuc9r832yicnc3u3092q3yq2p3yv23vq23nucq2n3nxoq2o3luoq2u3ocq3nroqwjr9q3umrxoqun3orvu3oun2′; // arbitrary
$my_vector = ‘12345678′; // arbitrary 8 char
$filter = new Zend_Filter_Decrypt(array(’key’ => ‘1′, ’salt’ => $my_salt, ‘vector’ => $my_vector)); // default (blowfish) + my salt + my vector
$decrypted = $filter->filter($password);
return $decrypted;
}
// decryption tests
$my_pass = decryptPassword($safe_my_pass);
$my_pass = base64_encode($my_pass);
echo(’<p> Decrypt test: ‘.$my_pass.’</p><p>Original Pass:’.$safe_my_pass.’</p>’);
what it outputs is:
Decrypt test: h7JclU+5qDxswBRMnrCWVv/Ypgs3vMhXAwaIVdInQ9Y=
Original Pass:ma84p6btUlt/xvDZDCyBAV/3b3t1gQLO
What am I doing wrong?
Also it seems that if key is provided the salt is useless… doesn’t change the outputted values… (you can take out: ’salt’ => $my_salt, and see what happens… is this normal???
Tuesday, October 20, 2009 - 01:06:24
Why should I explain all 200 algorithms, their options and what to be aware by using them, when there is a very good manual within php and mcrypt ?
I don’t see a reason to duplicate existing (and good) manuals.
Tuesday, October 20, 2009 - 01:11:42
I don’t see a reason why your code should work :-)
You encrypt the string… but then you trim it, do a base64 encoding and want to decrypt the CHANGED value.
Decryption works ONLY on the original encrypted UNCHANGED value.
Take a look into the manual or the testbed to see how decryption is done in normal situations.
Tuesday, October 20, 2009 - 07:53:54
Thanks, that actually cleared my problems! I guess I was too tired and couldn’t see the problem in front of my own eyes.
But I am still a bit confused as to what is the difference between a key and a salt and why when using a key, the salt get disregarded? (with the blowfish algo)
Is there something I could read to enlighten me on this issue?
Wednesday, January 13, 2010 - 16:37:00
Hi,
Nice writeup but there seems to be a bug in this implementation. If I use this method to set up a filter ZF keeps giving me the error ‘public key not valid’.
I looked at the code and found the reason. Apparenly if you instantiate a new Zend_Filter_Encrypt() and supply an array of options, the second index is always treated as being the public key, no matter what the key name is.
For example: array(’adapater’=>’openssl’, ‘private’ => ‘/path/to/mykey/private.pem’) will throw error ‘public key not valid’, because the key provided will be treated as a *public* key.
The way I worked around this is to use the method setPrivateKey on an instance of the filter class. This is the only way to set the private key.
The documentation on http://framework.zend.com/manual/en/zend.filter.set.html#zend.filter.set.encrypt.openssl is also wrong.
Wednesday, January 13, 2010 - 16:53:36
The previous issue has been picked up by someone nice enough to file a bug report:
http://framework.zend.com/issues/browse/ZF-8805
Friday, January 15, 2010 - 15:42:16
Please note that my blog is not ZF’s issue tracker.
Even if I work on those things I would appreciate it when people fill a official issue within Jira. This way problems and solutions are searchable for others who don’t read my blog.
PS: 8805 has already been fixed for the new ZF 1.10 Beta.
Friday, January 15, 2010 - 18:01:38
Great to hear it’s been fixed! Thanks again for the great writeup, your blog always offers an interesting read!
Tuesday, February 23, 2010 - 01:47:14
Great Article.
I am using mcrypt to return encrypted values which I pass as URL parameters. I cannot use anything else (like POST, SESSION or COOKIE) because this is a password reminder email. The email redirects the user to a page that is constructed using by decrypting one of the URL parameters.
Since mcrypt returns a bunch of garbage the decrypted value isn’t correct.
My question is that is there some way we can tell mcrypt to encode only using ASCII or Hex(preferebly).
THANKS
Saturday, February 27, 2010 - 12:11:13
Emails have the same limitation as url… you need to url-en/decode the string.
Simply compare the parameters when you encode/decode manually where you are sure that it works.
And then look at the parameters when you are doing the same with your email model.
Monday, April 12, 2010 - 10:19:04
hi,
I am trying to create a small application with zend and trying to use openssl encryption.i want when the user registers himself his password is encrypted and the encrypted password is sent to user through the link along with the envelope key , when the user clicks that link then the password gets decrypted and in the database its status is to be changed. but this is not happening as it is not decrypting the password.could you please help me in this.