Yii 1.1: Using phpseclib with Yii

6 followers

I installed phpseclib because I needed to do some AES encryption in my project. After all the hassle of installing php lib, I found out that Yii already has a security module (securityManager). I finally decided to keep using phpseclib because it has one big advantage over Yii securityManager module, it does not requite mcrypt to be installed in the phpserver!

Installing phpseclib is not as straightforward as you could imagine. Yii lazy loading (I think it is called like that) is not compatible with phpseclib files because classes are not called the same as the file names they are in.

Edit: As yiqing95 pointed out, the reason the names are not the same is because of a zend and pear naming convention so the zend autoloader should be used instead of my approach of modifying the third party library. Proceed at your own risk, but you better read yiqing95 comment.

-Steps to install phpseclib (modifying the library, not recommended now)-

(written on 2/Oct/2012, using Yii version 1.1.12. and phpseclib 0.3.0)

1) download phpseclib from: http://phpseclib.sourceforge.net

2) uncompress the downloaded archive, rename the folder to "phpseclib", and put it into your /vendors project directory.

3) rename all the files under /vendors/phpseclib/Crypt like this:

AES.php -> Crypt_AES.php

DES.php -> Crypt_DES.php

etc... (just prepend "Crypt_" in the file name)

4) search for "require_once" commands in those files and change them so they point to the new file names.

For example, in Crypt_AES.php change:

if (!class_exists('Crypt_Rijndael')) {
    require_once 'Rijndael.php';
}

to:

if (!class_exists('Crypt_Rijndael')) {
    require_once 'Crypt_Rijndael.php';
}

5) in config/main include phplib:

'import'=>array(
        ...
                'application.vendors.phpseclib.Crypt.*',
               ),

6) now you can use phplib in your project. For example within a model you can use:

public function encrypt($text){
  $cipher = new Crypt_AES();
  $cipher->setPassword('anypassword');
  return bin2hex($cipher->encrypt($text));
}

(see phplib documentation for more details)

Total 8 comments

#15883 report it
tab at 2013/12/26 06:20am
include(Math_BigInteger.php): failed to open stream: No such file or directory

Hi, after a long time spend to solve my issues I know the correct vendor path (in my case) was vendor and not vendors.

So, I have followed all steps of this tutorial but I have this issue: include(Math_BigInteger.php): failed to open stream: No such file or directory.

So, I think the problem is at line 464 of Crypt_RSA.php: if I remove

if (!class_exists('Math_BigInteger')) {

It works very fine. Why?

My versions are:

  • Yii - 1.1.last
  • phpseclib - 0.3.5
#15872 report it
tab at 2013/12/25 04:08am
include crypt_rsa.php: failed to open stream

Hi, I followed all steps of this tutorial but I have this problem when I call a new instance of RSA.

My versions are: Yii - 1.1.last phpseclib - 0.3.5

the system show this error:

1 unknown(0):YiiBase::autoload("Crypt_RSA")

#12295 report it
Ratty at 2013/03/11 11:39pm
Using Pear in General

yiqing95, provides a great solution to not changing the name. I used it with PHPCAS by doing the following:

Copied the code he provided to EZendAutoloader.php

And put this in my controller file under the action I wanted.

Yii::import("ext.zendautoloader.EZendAutoloader", true);
        EZendAutoloader::$basePath = Yii::getPathOfAlias("application.vendors.CAS").'/';
        // you can load not only Zend classes but also other classes with the same naming
        // convention
        EZendAutoloader::$prefixes = array( 'CAS');
        Yii::registerAutoloader(array("EZendAutoloader", "loadClass"), true);
        require_once('CAS.php');

Worked like a charm.

Cheers!

#10075 report it
nkd at 2012/10/03 09:44am
I am confused

I was writing the new version of the wiki but now I am a little bit confused. I downloaded the zendAutoloader extension and in the install instructions it says "Stripping all require_once from ZF. It is required for this extension and allows to load ZF classes faster."

So basically to run this extension you need comment out all the require_once in the zend (or in this case the phpseclib) libraries. Isn't this modifying the third party library also? I am starting to believe that my method of solving the issue is not that bad after all.

#10069 report it
nkd at 2012/10/03 08:00am
Re: Suggestion

Maurizio Domba: Yes. That is exactly what I am going to do but I need to try the new method first and then rewrite the whole wiki. The note I added is a temporal solution until I have the article written ;)

#10068 report it
Maurizio Domba Cerin at 2012/10/03 07:34am
Suggestion

nkd - why don't you rewrite the complete wiki so that instead leaving the "old" way of how not to do it you write about the "new" way of how to do it.

#10061 report it
nkd at 2012/10/03 01:46am
Re: should not rename the filename

@yiqing95: Very interesting, obviously I did not know about the zend and pear naming conventions. Thank you for pointing this out (I believe other people like me could make the same mistake in a desperate move to make a third party library work). I'll add a notice to the wiki pointing to your comment. Thank you!

#10059 report it
yiqing95 at 2012/10/02 10:25pm
should not rename the file name

the class and file name convention is compatible to Zend and PEAR . so you should use the ZendAutoLoader and add some code like this

EZendAutoloader::$basePath = Yii::getPathOfAlias("application.vendors.phpseclib").'/';
EZendAutoloader::$prefixes = array( 'Crypt');

the original zendAutoloader is used as static ,but better as a instance thus we can set different basePath or make it support multiple basePath ! or for simple just extract every dir under the phpsecclib to the vendors directory(don't need to modify the zendAutoloader just register the prefixes) .

any way thanks for introduce it to us . and don't modify any 3rd library unless have to

modified zendAutoLoader:

class EZendAutoloader {
    /**
     * @var array class prefixes
     */
    static $prefixes = array(
        'Zend'
    );
 
    /**
     * @var string path to where Zend classes root is located
     */
    static $basePath = null;
 
    /**
     * @var array
     * ---------------------------------
     * you can specify multiple basePath eg:
     * array(Yii::getPathOfAlias('application.vendors.phpseclib'),Yii::getPathOfAlias('application.extensions.Net')...);
     * ---------------------------------
     */
    static $basePaths = array();
 
    /**
     * Class autoload loader.
     *
     * @static
     * @param string $class
     * @return boolean
     */
    static function loadClass($className){
        foreach(self::$prefixes as $prefix){
            if(strpos($className, $prefix.'_')!==false){
                if(empty(self::$basePaths)){
                    if(!self::$basePath) self::$basePath = Yii::getPathOfAlias("application.vendors").'/';
                    include self::$basePath.str_replace('_',DIRECTORY_SEPARATOR ,$className).'.php';
                    return class_exists($className, false) || interface_exists($className, false);
                }else{
                    $classLoaded = false ;
                    foreach(self::$basePaths as $basePath){
 
                        include rtrim($basePath,'/\\'). DIRECTORY_SEPARATOR .str_replace('_',DIRECTORY_SEPARATOR ,$className).'.php';
                       if(class_exists($className, false) || interface_exists($className, false)){
                           return true ;
                       }
                    }
                    return $classLoaded ;
                }
            }
        }
        return false;
    }
}

Leave a comment

Please to leave your comment.

Write new article
  • Written by: nkd
  • Category: How-tos
  • Yii Version: 1.1
  • Votes: +2
  • Viewed: 6,601 times
  • Created on: Oct 2, 2012
  • Last updated: Oct 3, 2012
  • Tags: security