<?php
/**
 * Made By Frody: ffrody@gmail.com (H.S.Choi)
 *
 * 본인 이외에 복제/사용 금지
 */

class lcrypt {

  private $pwOpt = "kuls_";
  private $pwHash = true; //sha 한 비밀번호를 다시 unix hash 할것인지 여부

  //비밀번호 관련 함수
  public function pw_make($pass) { // 보안 패스워드를 반환 - sha256 해쉬함수 hash("sha256",$site_pw) vs MSSQL HASHBYTES('SHA2_512','passwd_text');
    if( $this->pwHash ){
      $site_pw = hash ( "sha256", base64_encode ( strtolower ( $pass ) . $this->pwOpt ) );
      $site_pw = password_hash( $site_pw, PASSWORD_DEFAULT);
    }else{
      $site_pw = hash ( "sha256", strtolower ( $pass ) . $this->pwOpt, true ); //Binary
    }
    return $site_pw;
  }

  public function pw_match($pass, $db_pass) { // 패스워드 체킹
    if( $this->pwHash ){
      $site_pw = hash ( "sha256", base64_encode ( strtolower ( $pass ) . $this->pwOpt ) );
      $pwd = password_verify( $site_pw, $db_pass );
    }else{
      $site_pw = hash ( "sha256", strtolower ( $pass ) . $this->pwOpt, true ); //Binary
      $pwd = ($site_pw == $db_pass);
    }

    if( $pwd ){
      return true;
    }
    return false;
  }

  public function setPwOpt($pw_opt){
    $this->pwOpt = $pw_opt;
  }

  public function setPwHash($bool){
    $this->pwHash = !!$bool;
  }

  //암복호화 함수
  public function enc_secure($sdata) {
    $enc_key = $this -> hex2bin( md5($this->pwOpt, TRUE) );
    $iv = $this -> hex2bin( md5($this->pwOpt, TRUE) );
    $encrypted = $this -> encrypt ($enc_key, $iv, $sdata);
    $encrypted = str_replace('+', '＋', $encrypted);
    return $encrypted?:'';
  }

  public function dec_secure($sdata) {
    $sdata = str_replace('＋', '+', $sdata);
    $enc_key = $this -> hex2bin( md5($this->pwOpt, TRUE) );
    $iv = $this -> hex2bin( md5($this->pwOpt, TRUE) );
    $decrypted = $this -> decrypt ($enc_key, $iv, $sdata);
    return $decrypted?:'';
  }

  public function hex2bin($hexdata){
    return $hexdata;
    $bindata = "";
    for( $i = 0 ; $i < strlen($hexdata) ; $i += 2 ){
      $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
    }
    return $bindata;
  }

  public function encrypt($key, $iv, $value){
    if( is_null($value) ){
      $value = "";
    }
    if( function_exists("mcrypt_encrypt") ){
      $value = $this->toPkcs7($value);
      $output = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $value, MCRYPT_MODE_CBC, $iv);
    }else{
      $output = openssl_encrypt($value, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
    }
    return base64_encode($output);
  }

  public function decrypt($key, $iv, $value){
    if( is_null($value) ){
      $value = "";
    }
    $value = base64_decode($value);
    if( function_exists("mcrypt_encrypt") ){
      $output = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $value, MCRYPT_MODE_CBC, $iv);
      $output = $this->fromPkcs7($output);
    }else{
      $output = openssl_decrypt($value, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
    }
    return $output;
  }

  private function toPkcs7($value){
    if( is_null($value) ){
      $value = "";
    }
    $padSize = 16 - intval(strlen($value) % 16);
    return $value.str_repeat(chr($padSize), $padSize);
  }

  private function fromPkcs7($value){
    $valueLen = strlen($value);
    if( $valueLen % 16 > 0 ){
      $value = "";
    }
    $padSize = ord($value[$valueLen - 1]);
    if( ( $padSize < 1 ) or ( $padSize > 16 ) ){
      $value = "";
    }
    // Check padding.
    for( $i = 0 ; $i < $padSize ; $i++ ){
      if( ord($value[$valueLen - $i - 1]) != $padSize ){
        $value = "";
      }
    }
    return substr($value, 0, $valueLen - $padSize);
  }
}