noka-encryption

Advertisement

<?php
###########################################################################################
#                                                                                         #
#    Copyright 2018 Khang H. Nguyen (kevinhg86)                                           #
#    E-mail: kevin@fai.host | Web: http://kevinhng86.iblog.website                        #
#    Contributors: https://github.com/kevinhng86/noka-encryption/blob/master/CONTRIBUTORS #                                                    #
#                                                                                         #    
#                                                                                         #
#    Permission is hereby granted, free of charge, to any person obtaining a copy         #
#    of this software and associated documentation files (the "Software"), to deal        #
#    in the Software without restriction, including without limitation the rights         #
#    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies     #
#    of the Software, and to permit persons to whom the Software is furnished             # 
#    to do so, subject to the following conditions:                                       #
#                                                                                         #
#    The above copyright notice and this permission notice shall be  included in all      #
#    copies or substantial portions of the Software.                                      #
#                                                                                         #
#    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR           #
#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,             #
#    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL              #
#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER           #
#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,        #
#    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN            #
#    THE SOFTWARE.                                                                        #
#                                                                                         #
###########################################################################################
    

class noka_encryption
{    
    private $hash_algo_1 = 'sha512';     // hash algo 1 and also is the default algo for the hash function if none was inputted. 
    private $hash_algo_2 = 'ripemd320';
    private $hash_algo_3 = 'gost';
    private $hash_algo_4 = 'haval256,5';
    private $hash_crypt_algo = 'sha512';     // sha512/sha256/blowfish 
    private $hash_encr_algo = 'aes-256-ctr';
    private $hash_encr_key = 'TVa1F6J0sDSWS6E+oN8hY!)s&U_hu=h~HiP`@_Nh';
    private $hash_k_1 = 'yG9!-9o3hG^6RchLR9ooJaC6k+naJU~8';
    private $hash_k_2 = 'e2hvHMK2vn0udd=SpiZ7Q*3&^mZ8+HBe';
    private $hash_k_3 = 'TLtNlE0xMyS_tct)F@IZ8qAxum6j4SDx';
    private $hash_k_4 = 'Y~!AESObyXlI6f$e*D504UY^^^TQw`z&';
    private $hash_pad_str = ')skvUtURrzhyY2@^nVZ`^1QwK8F8eK9b4^xym$@E';
    private $hash_pad_char = '0';
    private $pwd_len_max = 40;    
    private $encr_rounds = 7; 
    private $encr_algos = array('aes-256-xts','bf-ecb','aes-256-ctr','camellia-256-cbc','aes-128-cbc','aes-192-cbc','aes-192-ecb');    
    private $encr_keys = array('bkDRodvDk=c*2#ll3t!%o!z2ba#Uuqhw',
                                'Y~jTlqNFrIU_7rP9TL2A&Pmn7N0e_!9W',
                                'E`fSrYzlSpj&~WcKR_d8dJ@s!43T1PQf',
                                'S-2gUK_gQLc%hR1O%dvP3W-_bDIGRpHk',
                                'R2^k8(P4o(i*&`zd',
                                'MouBd9`7=gj^K*Aus!zgLAod',
                                'l=wfeC`%sDrJEcRH~sH^2Cl*');
    private $sep = '|';
    private $debug = false;
    public $version = '1.000';

    public function random_salt_blowfish(){
        
        $salt_pre = '$2a$';
        $salt_post = '$';
        $salt_low = 4;
        $salt_high = 9;
        $salt_char = '0123456789abcdefghijklmopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./';
        $salt_char_length = strlen($salt_char) - 1;
        $salt_length = 22;
        $salt_two_digit_cost = mt_rand( $salt_low , $salt_high );
        if ($salt_two_digit_cost < 10) $salt_two_digit_cost = "0" . $salt_two_digit_cost;        
        $str = $salt_pre . $salt_two_digit_cost . '$';

        for ( $i = 0 ; $i < $salt_length ; $i++ ){
            $str .=  $salt_char[mt_rand(0, $salt_char_length)];
        }

        return ($str . '$');
        
    }
    
    function random_salt_sha512(){

        $salt_char = '0123456789abcdefghijklmopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $salt_char_length = strlen($salt_char) - 1;
        $min = 5000;
        $max = 10000;
        $len = 16;
        $str = '$6$rounds=' . mt_rand( $min, $max ) . '$';
     
        for ( $i = 0; $i < $len; $i++ ){
            $str .= $salt_char[ mt_rand(0, $salt_char_length) ]; 
        }
    
        return ($str . '$');
    
    }


    function random_salt_sha256(){

        $salt_char = '0123456789abcdefghijklmopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $salt_char_length = strlen($salt_char) - 1;
        $min = 5000;
        $max = 10000;
        $len = 16;
        $str = '$5$rounds=' . mt_rand( $min, $max ) . '$';
     
        for ( $i = 0; $i < $len; $i++ ){
            $str .= $salt_char[ mt_rand(0, $salt_char_length) ]; 
        }
    
        return ($str . '$');
        
    }

    public function crypt ( $password , $algo = 'sha512' ){
        
        if ( !is_string($password) ) return false;
        if ( strlen($password) < 1 ) return false;
        if ( !is_string($algo) ) return false;    
        $algo = strtolower($algo);
        if ( $algo !== 'sha512' && $algo !== 'sha256' && $algo !== 'blowfish' ) return false;
        
        if ( $algo === 'blowfish' ) $salt = $this->random_salt_blowfish();
        if ( $algo === 'sha256' ) $salt = $this->random_salt_sha256();
        if ( $algo === 'sha512' ) $salt = $this->random_salt_sha512();
        
        $output = crypt($password, $salt);
        
        return (strlen($output) > 0 && $output !== '*0'? $output : false);
    }

    public function hash( $password , $key = null , $algo = null ){

    ################################################################################################################################
    #                                                                                                                              #
    # Arguments: *password, key, algo                                                                                              #
    # If "key" is an empty string or is null then the function will not use a key for hashing.                                     #
    # If "algo" is an empty string or is null then the function will use the value from the "hash_algo_1" variable of this class.  #
    #                                                                                                                              #
    ################################################################################################################################
        
        if( !is_string($password) ) return false;
        if( strlen($password) < 1 ) return false;
        if( (!is_string($key) && !is_null($key)) || (!is_string($algo) && !is_null($algo)) ) return false;
        
        if( strlen($algo) < 1 || is_null($algo) ) $algo = $this->hash_algo_1;

        if ( strlen($key) < 1 && !is_null($key) ){
            return hash_hmac($algo, $password, $key);
        } else {
            return hash($algo, $password);
        }
    }

    public function hashcrypt( array $args ){
        
    ####################################################################################################################################
    #                                                                                                                                  # 
    #    Arguments: array( *password: str, hash_key: str, hash_algo: str, mode: str(hex/raw) ;                                         #
    #    If "password" is not a string, is empty, or had not been set then the function will return a boolean false.                   #
    #    If "hash_key" is not set or is null then the index will be created and it will be set with a null value.                      #
    #    However, if "hash_key" is set but is not a string then the function will return a boolean false.                              #                                   
    #    The rule of "hash_key" is alo applied to "hash_algo".                                                                         #
    #    For the "mode", if "mode" is not set or is null then the the index will be created and set with the "hex" value               #
    #    If "mode" is set but does not equal to "hex" or "raw" then the function will return a boolean false.                          #
    #    For this function, when "mode" is set to hex, the function will return the hashed string in hexadecimal form.                 # 
    #    While in "raw" mode the function will return a raw crypt string.                                                              #
    #    Currently, this function only support sha256, sha512, and blowfish as the algorithms for the crypt() portion.                 #
    #    If for any reason the hash process fails to produce a result then a boolean false will be returned.                           #
    #                                                                                                                                  #
    ####################################################################################################################################
        
        if ( !isset($args['password']) ) return false;
        if ( !is_string($args['password']) ) return false;
        if ( strlen($args['password']) < 1 ) return false;

        if ( isset($args['hash_key']) ){
            if ( !is_string($args['hash_key']) ) return false;
            if ( strlen($args['hash_key']) < 1 ) return false;
        } else {
            $args['hash_key'] = null;
        }

        if ( isset($args['hash_algo']) ){
            if ( !is_string($args['hash_algo']) ) return false;
            if ( strlen($args['hash_algo']) < 1 ) return false;
        } else {
            $args['hash_algo'] = null;
        }
        
        if ( isset($args['crypt_algo']) ){
            if ( !is_string($args['crypt_algo']) ) return false;
            if ( strlen($args['crypt_algo']) < 1 ) return false;
        } else {
            $args['crypt_algo'] = $this->hash_crypt_algo;
        }


        if ( isset($args['mode']) ){
            if ( !is_string($args['mode']) ) return false;
            if ( $args['mode'] !== 'hex' && $args['mode'] !== 'raw' ) return false;
        } else {
            $args['mode'] = 'hex';
        }

        $password = $this->hash( $args['password'], $args['hash_key'], $args['hash_algo'] );
        if ( $password == false ) return $password;

        $password = $this->crypt( $password , $args['crypt_algo'] );
        if ( $args['mode'] === 'hex' ) $password = bin2hex( $password );

        return $password;
        
    }

    public function hash_double ( array $args ){
        
        if ( !isset($args['password']) ) return false;
        if ( !is_string($args['password']) ) return false;
        if ( strlen($args['password']) < 1 ) return false;

        if ( isset($args['hash_key_1']) ){
            if ( !is_string($args['hash_key_1']) ) return false;
            if ( strlen($args['hash_key_1']) < 1 ) return false;
        } else {
            $args['hash_key_1'] = null;
        }

        if ( isset($args['hash_key_2']) ){
            if ( !is_string($args['hash_key_2']) ) return false;
            if ( strlen($args['hash_key_2']) < 1 ) return false;
        } else {
            $args['hash_key_2'] = null;
        }


        if ( isset($args['hash_algo_1']) ){
            if ( !is_string($args['hash_algo_1']) ) return false;
            if ( strlen($args['hash_algo_1']) < 1 ) return false;
        } else {
            $args['hash_algo_1'] = null;
        }

        if ( isset($args['hash_algo_2']) ){
            if ( !is_string($args['hash_algo_2']) ) return false;
            if ( strlen($args['hash_algo_2']) < 1 ) return false;
        } else {
            $args['hash_algo_2'] = null;
        }

        $password = $this->hash( $args['password'], $args['hash_key_1'], $args['hash_algo_1'] );
        if ( $password == false ) return false;

        $password = $this->hash( $password, $args['hash_key_2'], $args['hash_algo_2'] );

        return $password;
        
    }

    public function nk_hash ( $password ){
        
        if ( !is_string($password) ) return false;
        if ( strlen($password) < 1 ) return false;

        // Pad the password so that all passwords are the same in length. This is to prevent timing guessing.
        $password = $this->pad( $password, $this->hash_pad_str, $this->pwd_len_max );

        // Encrypt the password before hashing, The encrypted version is in index 0. While the IV is in index 1.
        $password = $this->encrypt( $password, $this->hash_encr_algo, $this->hash_encr_key);
        
        // If the encryption process return false value then a boolean false value will be returned.
        if ( $password == false ) return false;
        
        // If the algorithm used for the encryption process did not utilize an IV string then a false value will be returned. 
        if ( strlen($password[1]) < 1 ) return false;

        // Create two hash version of the password for verification later.
        // The hash crypt version of the encrypted password.
        $hashcrypt = $this->hashcrypt( array( 'password' => $password[0],
                                            'hash_key' => $this->hash_k_1,
                                            'hash_algo' => $this->hash_algo_1,
                                            'crypt_algo' => $this->hash_crypt_algo,
                                            ) );
        if ( $hashcrypt == false ) return false;                                    

        // The hash double version of the encrypted password.
        $hashdouble = $this->hash_double( array( 'password' => $password[0],
                                                'hash_key_1' => $password[1],
                                                'hash_key_2' => $this->hash_k_2,
                                                'hash_algo_1' => $this->hash_algo_2,
                                                'hash_algo_2' => $this->hash_algo_3,
                                                ) );
                                                
        if ( $hashdouble == false ) return false;
        
        // The password string is now the hash crypt version, a seperator, a double hash version, and the IV.
        // All of the above are pre converted to a hex string because of the previous used functions.
        $password = $hashcrypt . $this->sep . $hashdouble . $this->sep . bin2hex($password[1]);

        return $password;
    }
    
    public function nk_flat ( $password ){
        
        if ( !is_string($password) ) return false;
        if ( strlen($password) < 1 ) return false;
                
        $password = $this->pad( $password, $this->hash_pad_str, $this->pwd_len_max );

        $password = $this->encrypt( $password, $this->hash_encr_algo, $this->hash_encr_key);

        if ( $password == false ) return false;

        // If the algorithm used for encryption did not utilize an IV string then a boolean false value will be returned. 
        if ( strlen($password[1]) < 1 ) return false;
        
        
        $hash_1 = $this->hash( $password[0], $this->hash_k_1, $this->hash_algo_1 );
        if ( $hash_1 == false ) return false;
        
        while ( strlen($hash_1) % 3 !== 0 ){
            $hash_1 .= $this->hash_pad_char;
        }
        
        $hash_1 = str_split( $hash_1, strlen($hash_1) / 3 );
        
        $hash_2 = $this->hash( $password[0] . $hash_1[0], $this->hash_k_2, $this->hash_algo_2 );
        if ( $hash_2 == false ) return false;
                
        $hash_3 = $this->hash( $password[0] . $hash_1[1], $this->hash_k_3, $this->hash_algo_3 );
        if ( $hash_3 == false ) return false;

        $hash_4 = $this->hash( $password[0] . $hash_1[2], $this->hash_k_4, $this->hash_algo_4 );
        if ( $hash_4 == false ) return false;

        $password = bin2hex($hash_2) . $this->sep . bin2hex($hash_3) . $this->sep . bin2hex($hash_4) . $this->sep . bin2hex($password[1]);
                
        return $password;
        
    }


    public function verify_hash( $password , $hash , $key = null , $algo = null ){
        
        if ( !is_string($password) ) return false;
        if ( strlen($password) < 1 ) return false;
        if ( !is_string($hash) ) return false;
        if ( strlen($hash) < 1 ) return false;
        if ( (!is_string($key) && !is_null($key)) || (!is_string($algo) && !is_null($algo)) ) return false;

        $password = $this->hash( $password, $key, $algo );

        if ( $password === $hash ){
            return true;
        } else {
            return false;
        }
    }

    public function verify_hash_double( array $args ){
        
        if ( !isset($args['password']) ) return false;
        if ( !is_string($args['password']) ) return false;
        if ( strlen($args['password']) < 1 ) return false;
            
        if ( !isset($args['hash_string']) ) return false;
        if ( !is_string($args['hash_string']) ) return false;
        if ( strlen($args['hash_string']) < 1 ) return false;

        if ( isset($args['hash_key_1']) ){
            if ( !is_string($args['hash_key_1']) ) return false;
            if ( strlen($args['hash_key_1']) < 1 ) return false;
        } else {
            $args['hash_key_1'] = null;
        }

        if ( isset($args['hash_key_2']) ){
            if ( !is_string($args['hash_key_2']) ) return false;
            if ( strlen($args['hash_key_2']) < 1 ) return false;
        } else {
            $args['hash_key_2'] = null;
        }


        if ( isset($args['hash_algo_1']) ){
            if ( !is_string($args['hash_algo_1']) ) return false;
            if ( strlen($args['hash_algo_1']) < 1 ) return false;
        } else {
            $args['hash_algo_1'] = null;
        }

        if ( isset($args['hash_algo_2']) ){
            if ( !is_string($args['hash_algo_2']) ) return false;
            if ( strlen($args['hash_algo_2']) < 1 ) return false;            
        } else {
            $args['hash_algo_2'] = null;
        }

        // Hashing round 1
        $args['password'] = $this->hash( $args['password'], $args['hash_key_1'], $args['hash_algo_1'] );
        if ( $args['password'] == false ) return false;

        // Hashing round 2
        $args['password'] = $this->hash( $args['password'], $args['hash_key_2'], $args['hash_algo_2'] );
        if ( $args['password'] == false ) return false;

        // Check if this hash version matched the inputed hash.
        if ( $args['password'] === $args['hash_string'] ) {
            return true;
        } else {
            return false;
        }
    }

    // Array: *str password, *str crypt_string, str hash_key, str hash_algo,
    public function verify_hashcrypt( array $args ){
        
        if ( !isset($args['password']) ) return false;
        if ( !is_string($args['password']) ) return false;
        if ( strlen($args['password']) < 1 ) return false;
        
        if ( !isset($args['crypt_string']) ) return false;
        if ( !is_string($args['crypt_string']) ) return false;
        if ( strlen($args['crypt_string']) < 1 ) return false;

        if ( isset($args['hash_key']) ){
            if ( !is_string($args['hash_key']) ) return false;
            if ( strlen($args['hash_key']) < 1 ) return false;
        } else {
            $args['hash_key'] = null;
        }

        if ( isset($args['hash_algo']) ){
            if ( !is_string($args['hash_algo']) ) return false;
            if ( strlen($args['hash_algo']) < 1 ) return false;
        } else {
            $args['hash_algo'] = null;
        }
                        
        // Hash the string first.
        $args['password'] = $this->hash( $args['password'], $args['hash_key'], $args['hash_algo'] );
        
        // If the hasshing process failed then return a boolean false value.
        if ( $args['password'] == false ) return false;

        // Verify if the hashed password matched the crypt() version of it.
        return password_verify( $args['password'], $args['crypt_string'] );
        
    }

    public function verify_nk_hash ( $password , $hash ){
        
        if ( !is_string($password) ) return false;
        if ( strlen($password) < 1 ) return false;
        if ( !is_string($hash) ) return false;
        if ( strlen($hash) < 1 ) return false;
        
        $hash = explode( $this->sep, $hash );
        if ( count($hash) < 3 ) return false;
        
        ################################################################
        #                                                              #
        # Hashcrypt, hex to bin.                                       #
        # 0 = Crypt() string.                                          #
        # 1 = Double hash string.                                      #
        # 2 = IV for encryption.                                       # 
        #                                                              #
        ################################################################
        
        $hash[0] = hex2bin( $hash[0] );
        $hash[2] = hex2bin( $hash[2] );

        // Since noka_hash padded the password.
        // Thus, the password is padded before being encrypted.
        $password = $this->pad( $password, $this->hash_pad_str, $this->pwd_len_max );
        
        // Encrypt the password before hashing. This time, we only need the encryption string and not the IV.
        $password = $this->encrypt( $password, $this->hash_encr_algo, $this->hash_encr_key, OPENSSL_RAW_DATA, $hash[2] )[0];

        // Verify the hash crypt() version of the password. 
        $hc = $this->verify_hashcrypt( array( 'password' => $password,
                                            'crypt_string' => $hash[0],
                                            'hash_key' => $this->hash_k_1,
                                            'hash_algo' => $this->hash_algo_1,
                                            ));
                                            
        // Verify the double hash version of the password.
        $hh = $this->verify_hash_double( array( 'password' => $password,
                                                'hash_string' => $hash[1],
                                                'hash_key_1' => $hash[2],
                                                'hash_key_2' => $this->hash_k_2,
                                                'hash_algo_1' => $this->hash_algo_2,
                                                'hash_algo_2' => $this->hash_algo_3,
                                                ));
                                                
        // Only return true if both, the hash crypt() and the hash hash version of the password matched the original(Stored) hash.
        if ( $hc === true && $hh === true ){
            return true;
        } else {
            return false;
        }
    }
    
    public function verify_nk_flat( $password , $hash ){
        
        if ( !is_string($password) ) return false;
        if ( strlen($password) < 1 ) return false;
        if ( !is_string($hash) ) return false;
        if ( strlen($hash) < 1 ) return false;
        
        $hash = explode( $this->sep, $hash );
        
        if ( count($hash) < 4 ) return false;

        for ( $i = 0; $i < 4; $i++ ){
            if ( !ctype_xdigit($hash[$i]) ) return false;
            $hash[$i] = hex2bin( $hash[$i] );
        }
        
        $password = $this->pad( $password, $this->hash_pad_str, $this->pwd_len_max );

        $password = $this->encrypt( $password, $this->hash_encr_algo , $this->hash_encr_key, OPENSSL_RAW_DATA, $hash[3] )[0];
    
        $hash_1 = $this->hash( $password, $this->hash_k_1, $this->hash_algo_1 );
        
        if ( $hash_1 == false ) return false;
        
        while ( strlen($hash_1) % 3 !== 0 ){
            $hash_1 .= $this->hash_pad_char;
        }
        
        $hash_1 = str_split( $hash_1, strlen($hash_1) / 3 );
        
        $hash_2 = $this->hash( $password . $hash_1[0], $this->hash_k_2, $this->hash_algo_2 );
        if ( $hash_2 == false ) return false;
                
        $hash_3 = $this->hash( $password . $hash_1[1], $this->hash_k_3, $this->hash_algo_3 );
        if ( $hash_3 == false ) return false;

        $hash_4 = $this->hash( $password . $hash_1[2], $this->hash_k_4, $this->hash_algo_4 );
        if ( $hash_4 == false ) return false;

        $h2 = $hash_2 === $hash[0];
        $h3 = $hash_3 === $hash[1];
        $h4 = $hash_4 === $hash[2];

        if ( $h2 === true && $h3 === true && $h4 === true ){
            return true;
        } else {
            return false;
        }
    } 
    


    // Arguments: Message, Algo, Key, Option(0/*OPENSSL_RAW_DATA)
    function encrypt( $msg, $algo, $key, $options = OPENSSL_RAW_DATA, $iv = null ) {
        
        if ( !is_string($msg) ) return false;
        if ( strlen($msg) < 1 ) return false;
        if ( !is_string($algo) ) return false;
        if ( strlen($algo) < 1 ) return false;
        if ( !in_array($algo, openssl_get_cipher_methods()) ) return false;
        if ( !is_string($iv) && !is_null($iv) ) return false;
        
        if ( is_null($options) ) $options = OPENSSL_RAW_DATA;
        
        $ivlen = openssl_cipher_iv_length($algo);

        if ( is_null($iv) || strlen($iv) < 1 ){
            $iv = $ivlen > 0? openssl_random_pseudo_bytes($ivlen) : '';
        }

        if ( strlen($iv) != $ivlen ) return false;

        $output = openssl_encrypt($msg, $algo, $key, $options, $iv);

        return array($output, $iv);
    }

    // Arguments: Cipher Text, Algo, Key, IV, Option(0/*OPENSSL_RAW_DATA)
    function decrypt( $cipher_text, $algo, $key, $iv, $options = OPENSSL_RAW_DATA ){

        if ( !is_string($cipher_text) ) return false;
        if ( strlen($cipher_text) < 1 ) return false;
        if ( !is_string($key) ) return false;
        if ( strlen($key) < 1 ) return false;
        if ( !is_string($iv) ) return false;                
        
        if ( !in_array($algo, openssl_get_cipher_methods()) ) return false;

        return openssl_decrypt($cipher_text, $algo, $key, $options, $iv);
    }


    // Array: str password , array key , array algo , str mode
    public function nk_encrypt( $text, $round, $key = null, $algo = null, $mode = 'hex' ){
        
        if ( !is_string($text) ) return false;
        if ( strlen($text) < 1 ) return false;
        if ( !is_int($round) ) return false;
        
        if ( !is_array($key) && !is_null($key) ) return false;
        if ( !is_array($algo) && !is_null($algo) ) return false; 
        if ( !is_string($mode) ) return false; 
        if ( $mode !== 'hex' && $mode !== 'raw' ) return false;

        if ( $algo === null ) $algo = $this->encr_algos;
        if ( $key === null ) $key = $this->encr_keys;

        $ck = count($key);
        $ca = count($algo);

        if ( $ck < 1 || $ca < 1 ) return false;

        for ( $i = 0; $i < count($key); $i++ ){
            if ( !is_string($key[$i]) ) return false;
            if ( strlen($key[$i]) < 1 ) return false;
        }

        for ( $i = 0; $i < count($algo); $i++ ){
            if ( !is_string($algo[$i]) ) return false;
            if ( !in_array($algo[$i], openssl_get_cipher_methods()) ) return false;
        }

        $text = $this->str_to_block($text);
        $text = $this->random_pad_hex($text);    
        $ik = 0;
        $ia = 0;
        $ivlen = 0;

        for ( $i = 0; $i < $round; $i++ ){
            if ( $ik >= $ck ) $ik = 0;
            if ( $ia >= $ca ) $ia = 0;
            
            $text = $this->encrypt( $text, $algo[$ia], $key[$ik] );
                        
            if ( $text === false || !is_array($text) ) return false;
            
            $text = $text[0] . $text[1];

            $ia++; $ik++;
        }
        
        if ( $mode === 'hex' ) $text = bin2hex($text);
        
        return $text;

    }

    // Array: str password , array key , array algo , str mode
    public function nk_decrypt( $c_text, $round, $key = null, $algo = null, $input_mode = 'hex' ) {
        
        if ( !is_string($c_text) ) return false;
        if ( strlen($c_text) < 1 ) return false;
        if ( !is_int($round) ) return false;

        if ( !is_array($key) && !is_null($key) ) return false;
        if ( !is_array($algo) && !is_null($algo) ) return false; 
        if ( !is_string($input_mode) ) return false; 
        if ( $input_mode !== 'hex' && $input_mode !== 'raw' ) return false;

        if ( $algo === null ) $algo = $this->encr_algos;
        if ( $key === null ) $key = $this->encr_keys;

        $ck = count($key);
        $ca = count($algo);

        if ( $ck < 1 || $ca < 1 ) return false;

        for ( $i = 0; $i < count($key); $i++ ){
            if ( !is_string($key[$i]) ) return false;
        }

        for ( $i = 0; $i < count($algo); $i++ ){
            if ( !is_string($algo[$i]) ) return false;
            if ( !in_array($algo[$i], openssl_get_cipher_methods()) ) return false;
        }

        if ( $input_mode === 'raw' ) $c_text = bin2hex($c_text);

        // Count Round
        $ik = 0;
        $ia = 0;
        $iv = '';
        $ivlen = 0;
        $r = array();
        
        for ( $i = 0; $i < $round; $i++ ){
            if ( $ik >= $ck ) $ik = 0;
            if ( $ia >= $ca ) $ia = 0;

            $r[$i] = array( 'k' => $ik, 'a' => $ia );
            $ik++; $ia++;
        }


        for ( $i = $round - 1; $i > -1; $i-- ){
            $ivlen = openssl_cipher_iv_length( $algo[$r[$i]['a']] ) * 2;
            
            if ( $ivlen > 0 ) {
                $iv = hex2bin( substr( $c_text, $ivlen * -1 ) );
                $c_text = substr( $c_text, 0, strlen($c_text) - $ivlen );
            } else {
                $iv = '';
            }

            $c_text = hex2bin( $c_text );
            $c_text = bin2hex( $this->decrypt( $c_text, $algo[ $r[$i]['a'] ], $key[ $r[$i]['k'] ], $iv) );
        }
        
        $c_text = hex2bin( $c_text );
        $c_text = $this->random_pad_hex_remove( $c_text );
        $c_text = $this->block_to_str( $c_text );

        return $c_text;
    }

    function generate_key( $len ){
        
        if( !is_int($len) ) return false;
        
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ0123456789-=`~!@#$%^&*()_+';
        $chars_len = strlen($chars) - 1;
        $output = '';
        
        for ( $i = 0; $i < $len; $i++ ){
            $output .= $chars[rand(0, $chars_len)];
        }

        return $output;
    }

    function pad ( $password , $pad_str, $pad_len , $side = STR_PAD_LEFT ){
        
        if ( !is_string($password) ) return false;
        if ( strlen($password) < 1 ) return false; 
        if ( !is_string($pad_str) ) return false;
        if ( !is_int($pad_len) ) return false;
        if ( !is_int($side) ) return false;
        if ( $side > 1 ) return false;
        if ( $pad_len !== strlen($pad_str) ) return false;
        if ( strlen($password) > $pad_len ) return $password;

        if ( $side === 0 ){
            $password = substr($pad_str . $password, $pad_len * -1);
        } else {
            $password = substr($password . $pad_str, 0, $pad_len);
        }

        return $password;
    }

    function str_to_block ( $str ){
        
        if ( !is_string($str) ) return false;
        if ( strlen($str) < 1 ) return false;
        #################################################################################
        #                                                                               #
        #  1 byte = 2 hex = 8 bit.                                                      #  
        #  1 block = 80 bits = 10 hex = 5 chars                                         #
        #                                                                               #
        #  More than 3 blocks:                                                          #
        #  1 block = 10 random hex + 10 hex(5 bytes) of original text.                  #
        #                                                                               #
        #  3 blocks to less:                                                            #
        #  1 block = 1(ff or f0) + 8 random hex + 10 hex(5 bytes) of original text.     #
        #                                                                               #
        #  This function take in a text string, Split it into chunks of fives. Then it  #
        #  will add four to five randoms chars in front of every blocks of text.        #
        #  This function does all the above steps in hexadecimal and will return a      #
        #  hexadecimal string.                                                          #
        #                                                                               #
        #################################################################################
        $str = bin2hex($str);
        // Original text block size in hex
        $size = 10;
        // Full block size after padded in hex
        $size_full = $size * 2;
        // Minimum blocks
        $min = 3;
        
        while ( (strlen($str) % $size) !== 0){
            $str = '00' . $str;
        }
    
        $str = str_split( $str, $size );
        $block = count($str);
    
        if ( $block <= $min ){
        
            $short = $min - $block;
            $short_array = array();
            #####################################################################################################
            #                                                                                                   #
            #    If we have to make a block because there was not enough text to generate the minimum           #
            #    blocks that needed then we generate that block with all random hex. We will prefix the         #
            #    random block with f0 so that we can identify them later. For blocks that had original texts,   #
            #    we will prefix the block with ff so that the random generator doesn't place an f0 there.       #
            #                                                                                                   #
            #####################################################################################################
            $pre_short = 'f0';
            $pre_norm = 'ff';
        
            for ( $i = 0; $i < $short; $i++ ){
                $c = 0;
                $short_array[$i] = '';

                while ( $c < ($size_full - 2) ){
                    $short_array[$i] .= bin2hex( chr( mt_rand(1, 255) ) );
                    $c = $c + 2;
                }
            
                $short_array[$i] = $pre_short . $short_array[$i];    
            }
        

            for ( $i = 0; $i < $block; $i++ ){
                $c = 0;
            
                while ( $c < ($size - 2) ){
                    $str[$i] = bin2hex( chr( mt_rand(1, 255) ) ) . $str[$i];
                    $c = $c + 2;
                }
            
                $str[$i] = $pre_norm . $str[$i];
            }
    
            $str = array_merge( $short_array, $str );
        
        } else {
        
            for ( $i = 0; $i < $block; $i++ ){
                $rand = '';
                $c = 0;
                while ( $c < $size ){
                    // This can also be written as $str[$i] = bin2hex( chr( mt_rand(1, 255) ) ) . $str[$i];
                    // with the removal of "rand" and "c" variable plus the while loop's condition change to strlen($str[$i]) < $size_full.
                    // However, the script was tested to operate much faster when written like this.
                    $rand .= bin2hex( chr( mt_rand(1, 255) ) );
                    $c = $c + 2;
                }
                $rand .= $str[$i];
                $str[$i] = $rand;
            }
        
        }    
    
        $str = implode($str);

        return $str;

    }

    function block_to_str ( $str ){
    
        if ( !is_string($str) ) return false;
        if ( strlen($str) < 1 ) return false;
        if ( !ctype_xdigit($str) ) return false;
    
        #######################################################################
        #                                                                     #
        #   This function take in a hex string that produced by str_to_block  #
        #   and convert that string back to the original input. This          #
        #   function will return false if input is not hex, is not a string   #
        #   or is not divisible by the size of the full block implemented by  #
        #   the str_to_block function.                                        #
        #                                                                     #
        #######################################################################
        $size_full = 20;
        $size = $size_full / 2;
        $min = 3;
        $prefix_short = "f0";
        $len = strlen($str);
    
        if ( $len % $size_full !== 0 ) return false;

        $str = str_split($str, $size_full);
        $block = count($str);
    
        if ( $block <= $min ){
        
            for ( $i = 0; $i < $block; $i++ ){
            
                if ( strpos($str[$i], $prefix_short) === 0 ){
                    unset( $str[$i] );
                } else {
                    $str[$i] = substr( $str[$i], $size );
                }
            
            }
        
        } else {
        
            for ( $i = 0; $i < $block; $i++ ){
                $str[$i] = substr( $str[$i], $size );
            }
    
        }    

        $str = implode($str);
        $str = ltrim($str, '0');
        $len = strlen($str);
        
        if ( $len % 2 !== 0 ) $str = "0" . $str;             
        if ( $len === 0 ) $str = '00';

        $str = hex2bin($str);

        return $str;

    }
    
    function random_pad_hex ( $str ){
    
        if ( !is_string($str) ) return false;
        if ( ($len = strlen($str)) < 1 ) return false;
        if ( !ctype_xdigit($str) ) return false;
        
        $hex = array ( '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' );
        $str .= $this->sep;
        $max = $len < 500? 500 : 100;
    
        $round = mt_rand(1 , $max);

        for ( $i = 0; $i < $round; $i++ ){
            $str .= $hex[mt_rand(0, 15)] . $hex[mt_rand(0, 15)];
        } 
    
        return $str;
    }

    function random_pad_hex_remove ( $str ){

        if ( !is_string($str) ) return false;
        if ( strlen($str) < 1 ) return false;

        $str = explode( $this->sep, $str );
    
        if ( count($str) !== 2 ) return false;
    
        return $str[0];
        
    }
    
}

?>
Advertisement


Random Article You May Like