<?php
/* SVN FILE: $Id: rkt_crypt.php 270 2008-05-06 23:16:41Z bb_yujiro $ */
/**
 * 暗号化/複号クラス
 *
 * PHP versions 5
 *
 *      hitSuji : Social Network Service <http://rakuto.net/rktSNS/>
 *      Copyright (c) 2007 Yujiro Takahashi
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @filesource
 * @package         hitSuji
 * @copyright       Copyright (c) 2007 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @version         $Revision: 270 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-05-07 08:16:41 +0900 (水, 07 5 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */

/**
 * 暗号化クラス
 *
 * @category        Encryption
 * @package         hitSuji
 * @copyright       Copyright (c) 2007 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @version         $Revision: 270 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-05-07 08:16:41 +0900 (水, 07 5 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */
class RKT_Crypt
{
    /**
     * Singleton用インスタンス
     * @var object
     */
    private static $_instance;

    /**
     * 暗号化オブジェクト
     * @access private
     * @var object
     */
    private $_crypt = null;

    /**
     * コンストラクタ
     *
     * @access private
     * @return void
     */
    private function __construct($key=PASS_PHRASE)
    {
        include LIB_DIR.'PEAR/Crypt/Blowfish.php';

        $this->_crypt = new Crypt_Blowfish($key);
    }

    /**
     * Singleton メソッド
     *
     * @access public
     * @param string $driver
     * @param string $param
     * @return object __CLASS__
     */
    public static function getInstance($key=PASS_PHRASE)
    {
        if (!isset(self::$_instance)) {
            $classname = __CLASS__;
            self::$_instance = new $classname($key);
        }
        return self::$_instance;
    }

    /**
     * データの暗号化
     *
     * @access public
     * @param string $plain
     * @return binary 暗号化されたデータ
     */
    public function encrypt($plain)
    {
        if (empty($plain)){
            return null;
        }
        $crypted = $this->_crypt->encrypt($plain);
        if (PEAR::isError($crypted)) {
            error_log('RKT_Crypt::encrypt();'."\t".
                        $crypted->getMessage()."\r\n", 3, ERROR_LOG_FILE);
            return null;
        }
        return $crypted;
    }
    
    /**
     * データの復号
     *
     * @access public
     * @param string $crypted
     * @return string プレーンデータ
     */
    public function decrypt($crypted)
    {
        $plain = $this->_crypt->decrypt($crypted);
        if (PEAR::isError($plain)) {
            error_log('RKT_Crypt::decrypt();'."\t".
                        $plain->getMessage()."\r\n", 3, ERROR_LOG_FILE);
            return null;
        }
        return $plain;
    }

    /**
     * 16進数からバイナリデータへ
     *
     * @access public
     * @param  string  $hex     16進数
     * @return binary バイナリデータ
     */
    public static function hex2bin($hex)
    {
        $length = strlen($hex);
        return pack('H' . $length, $hex);
    }

    /**
     * 暗号化データの取得
     *
     * @access public
     * @param string $plain
     * @param string $output_func
     * @return string 暗号化されたデータ
     */
    public static function getEncrypted($plain, $output_func=CRYPT_OUTPUT_FUNC)
    {
        $ojbcyt = self::getInstance();

        $crypted = $ojbcyt->encrypt($plain);
        return call_user_func($output_func, $crypted);
    }

    /**
     * 復号データの取得
     *
     * @access public
     * @param string $crypted
     * @param string $output_func
     * @return string プレーンデータ
     */
    public static function getDecrypted($crypted, $input_func=CRYPT_INPUT_FUNC)
    {
        $ojbcyt = self::getInstance();

        $crypted = call_user_func($input_func, $crypted);
        $result  = $ojbcyt->decrypt($crypted);
        return trim($result);
    }

    /**
     * ハッシュデータの取得
     *
     * @access public
     * @param string $plain
     * @param string $hash_func
     * @return string ハッシュデータの
     */
    public static function getHashed($plain, $hash_func=HASH_FUNC)
    {
        return call_user_func($hash_func, $plain);
    }

    /**
     * Nonceデータの取得
     *
     * @access public
     * @param string $seed
     * @return string Nonceデータ
     */
    public static function getNonce($seed='')
    {
        $extra = empty($_SESSION['extraTime'])? 0:$_SESSION['extraTime'];
        $extra = is_numeric($extra)? $extra:0;
        $extra = ($extra >= 0 && $extra < NONCE_LIFE_TIME)? $extra:0;
        $now   = time();
        
        $timer = ceil(($now + $extra) / NONCE_LIFE_TIME);
        
        /* htdocs/exec.phpでrkt_account.phpをInclude済み */
        $accid  = RKT_account::exec()->getAccountID();
        
        $plain  = $timer.$accid.$extra.$seed;        
        $hashed = self::getHashed($plain);

        return substr($hashed, -14, 10);
    }

    /**
     * Seedデータの取得
     *
     * @access public
     * @param string $plain
     * @return string Seedデータ
     */
    public static function getSeed($plain)
    {
        $seed = md5($plain.PASS_SEED);
        return substr($seed, 4, 6);
    }

    /**
     * Keyデータの取得
     *
     * @access public
     * @param string $plain
     * @return string Keyデータ
     */
    public static function getKey($plain, $seed)
    {
        return md5($seed.$plain.PASS_SEED);
    }
} // RKT_crypt
?>
