Вход Регистрация
Файл: public_html/lib/wmxi/WMSigner.php
Строк: 274
<?php
################################################################################
#                                                                              #
# Webmoney Signer PHP edition by DKameleon (http://dkameleon.com)              #
#                                                                              #
# Updates and new versions: http://my-tools.net/wmxi/                          #
#                                                                              #
# Server requirements:                                                         #
# - BCMath or GMP                                                              #
# - MD4 or MHash or Hash                                                       #
#                                                                              #
################################################################################


# including classes
if (!defined('__DIR__')) { define('__DIR__'dirname(__FILE__)); }
require_once(
__DIR__ DIRECTORY_SEPARATOR 'WMXILogger.php');
if (
file_exists(__DIR__ DIRECTORY_SEPARATOR 'MD4.php')) { include_once(__DIR__ DIRECTORY_SEPARATOR 'MD4.php'); }


# WMSigner class
class WMSigner {

    private 
$wmid '';

    private 
$ekey '';
    private 
$nkey '';

    private 
$md4_use  '';
    private 
$math_use '';
    
    private 
$md4     null;

    
# debug switch
    
private $debug false;

    
# constructor
    
public function __construct($wmid$key) {
        
$this->debug defined('WMXI_LOG');
    
        
$this->math_use $this->InitMath();
        
$this->md4_use  $this->InitMD4();
        
WMXILogger::Append("$this->math_use = ".$this->math_use.";");
        
WMXILogger::Append("$this->md4_use = ".$this->md4_use.";");
    
        
$this->wmid $wmid;

        
# loading e-n-key
        
if (isset($key['ekey']) && isset($key['nkey'])) {
            
$this->ekey $key['ekey'];
            
$this->nkey $key['nkey'];
            return 
true;
        }

        
$pass = isset($key['pass']) ? $key['pass'] : '';
        if (isset(
$key['file'])) {
            if (!
file_exists($key['file'])) { die('Key file not found: ' $key['file']); }
            
$data file_get_contents($key['file']);
        }
        if (isset(
$key['data'])) { $data $key['data']; }
        
# seems can be another size (162 bytes)
#        if ($this->_strlen($data) != 164) { die('Key data has invalid size: ' . $this->_strlen($data)); }

        // extracting n & e from data
        
$key_data unpack('vreserved/vsignflag/a16crc/Vlen/a*buf'$data);
        
$key_test $this->SecureKeyByIDPW($wmid$pass$key_data);
        
$sign_keys $this->InitKeys($key_test);
        
$this->ekey $this->_hex2dec(bin2hex(strrev($sign_keys['ekey'])));
        
$this->nkey $this->_hex2dec(bin2hex(strrev($sign_keys['nkey'])));
    }


    
# export keys for feature usage
    
public function ExportKeys() {
        return array(
'ekey' => $this->ekey'nkey' => $this->nkey);
    }


    
# Math init
    
private function InitMath() {
        if (
defined('WMXI_MATH')) {
            switch (
WMXI_MATH) {
                case 
'gmp': if (extension_loaded('gmp')) { return WMXI_MATH; } break;
                case 
'bcmath5': if (function_exists('bcpowmod')) { return WMXI_MATH; } break;
                case 
'bcmath4': if (extension_loaded('bcmath')) { return WMXI_MATH; } break;
            }
            die(
'Can not use WMXI_MATH = 'WMXI_MATH);
        } else {
            if (
extension_loaded('gmp')) { return 'gmp'; } 
            if (
function_exists('bcpowmod')) { return 'bcmath5'; } 
            if (
extension_loaded('bcmath')) { return 'bcmath4'; } 
            die(
'Supported math implementations not found.');
        }
    }

    
    
# MD4 init
    
private function InitMD4() {
        if (
defined('WMXI_MD4')) {
            switch (
WMXI_MD4) {
                case 
'mhash': if (function_exists('mhash')) { return WMXI_MD4; } break;
                case 
'hash':  if (function_exists('hash')) { return WMXI_MD4; } break;
                case 
'class': if (class_exists('MD4')) { $this->md4 = new MD4(true); return WMXI_MD4; } break;
            }
            die(
'Can not use WMXI_MD4 = 'WMXI_MD4);
        } else {
            if (
function_exists('mhash')) { return 'mhash'; }
            if (
function_exists('hash')) { return 'hash'; }
            if (
class_exists('MD4')) {
                
$this->md4 = new MD4(true);
                return 
'class';
            }
            die(
'Supported MD4 implementations not found.');
        }
    }

    private function 
_strlen($data) {
        return 
mb_strlen($data'windows-1251');
    }
    
    
# md4 wrapper
    
private function _md4($data) {
        if (
$this->md4_use == 'mhash') { return mhash(MHASH_MD4$data); }
        if (
$this->md4_use == 'hash' ) { return hash('md4'$datatrue); }
        if (
$this->md4_use == 'class') { return $this->md4->Calc($datatrue); }
        die(
'MD4 implementations not found for _md4.');
    }


    
# bcpowmod wrapper for old PHP
    
private function _bcpowmod($m$e$n) {
        if (
$this->math_use == 'gmp') { return gmp_strval(gmp_powm($m$e$n)); }
        if (
$this->math_use == 'bcmath5') { return bcpowmod($m$e$n); }
        if (
$this->math_use == 'bcmath4') {
            
$r '';
            while (
$e != '0') {
                
$t bcmod($e'4096');
                
$r substr('000000000000'.decbin(intval($t)), -12).$r;
                
$e bcdiv($e'4096'0);
                
WMXILogger::Append("$t = $t$e = $e;");
            }
            
$r preg_replace('!^0+!'''$r);
            if (
$r == ''$r '0';
            
$m bcmod($m$n);
            
WMXILogger::Append("$m = $m;");
            
$erb strrev($r);
            
WMXILogger::Append("$erb = $erb;");
            
$result '1';
            
$a[0] = $m;
            for (
$i 1$i $this->_strlen($erb); $i++) {
                
$a[$i] = bcmod(bcmul($a[$i-1], $a[$i-1], 0), $n);
            }
            
WMXILogger::Append("$a = $a;");
            for (
$i 0$i $this->_strlen($erb); $i++) {
                if (
$erb[$i] == '1') {
                    
$result bcmod(bcmul($result$a[$i], 0), $n);
                }
            }
            
WMXILogger::Append("$result = $result;");
            return 
$result;
        }
        die(
'Math implementations not found for _bcpowmod.');
    }


    
# convert decimal to hexadecimal
    
private function _dec2hex($number) {
        if (
$this->math_use == 'gmp') {
            
$hexval gmp_strval($number16);
            if (
$this->_strlen($hexval) % 2) { $hexval '0'.$hexval; }
            
WMXILogger::Append("$hexval = $hexval;");
            return 
$hexval;
        }
        if (
$this->math_use == 'bcmath4' || $this->math_use == 'bcmath5') {
            
$hexvalues = array('0''1''2''3''4''5''6''7''8''9''A''B''C''D''E''F');
            
$hexval '';
            while(
$number != '0') {
                
$hexval $hexvalues[bcmod($number'16')].$hexval;
                
$number bcdiv($number'16'0);
            }
            if (
$this->_strlen($hexval) % 2) { $hexval '0'.$hexval; }
            
WMXILogger::Append("$hexval = $hexval;");
            return 
$hexval;
        }
        die(
'Math implementations not found for _dec2hex.');
    }


    
# convert hexadecimal to decimal
    
private function _hex2dec($number) {
        if (
$this->math_use == 'gmp') { return gmp_strval("0x$number"10); }

        if (
$this->math_use == 'bcmath4' || $this->math_use == 'bcmath5') {
            
$decvalues = array(
                
'0' => '0''1' => '1''2' => '2''3' => '3',
                
'4' => '4''5' => '5''6' => '6''7' => '7',
                
'8' => '8''9' => '9''A' => '10''B' => '11',
                
'C' => '12''D' => '13''E' => '14''F' => '15');
            
$decval '0';
            
$number strrev(strtoupper($number));
            
WMXILogger::Append("$number = $number;");
            for(
$i 0$i $this->_strlen($number); $i++) {
                
$decval bcadd(bcmul(bcpow('16'$i0), $decvalues[$number[$i]], 0), $decval0);
            }
            
WMXILogger::Append("$decval = $decval;");
            return 
$decval;
        }
        die(
'Math implementations not found for _hex2dec.');
    }


    
# swap hexadecimal string
    
private function _shortunswap($hex_str) {
        
$result '';
        while(
$this->_strlen($hex_str) < 132) { $hex_str '00'.$hex_str; }
        for(
$i 0$i $this->_strlen($hex_str) / 4$i++) {
            
$result substr($hex_str$i 44).$result;
        }
        return 
$result;
    }


    
# XOR two strings
    
private function _XOR($str$xor_str$shift 0) {
        
$str_len $this->_strlen($str);
        
$xor_len $this->_strlen($xor_str);
        
$i $shift;
        
$k 0;
        while (
$i $str_len) {
            
$str[$i] = chr(ord($str[$i]) ^ ord($xor_str[$k]));
            
$i++;
            
$k++;
            if (
$k >= $xor_len) { $k 0; }
        }
        return 
$str;
    }


    
# both of SecureKeyByIDPW
    
private function SecureKeyByIDPW($wmid$pass$key_data) {
        
$digest $this->_md4($wmid $pass);
        
$result $key_data;
        
$result['buf'] = $this->_XOR($result['buf'], $digest6);
        return 
$result;
    }


    
# initializing E and N
    
private function InitKeys($key_data) {
        
$crc_cont '';
        
$crc_cont .= pack('v'$key_data['reserved']);
        
$crc_cont .= pack('v'0);
        
$crc_cont .= pack('V4'0000);
        
$crc_cont .= pack('V'$key_data['len']);
        
$crc_cont .= $key_data['buf'];
        
$digest $this->_md4($crc_cont);
        if (
strcmp($digest$key_data['crc'])) { die('Checksum failed. KWM seems corrupted.'); }

        
$keys unpack('Vreserved/ve_len'$key_data['buf']);
        
$keys unpack('Vreserved/ve_len/a'.$keys['e_len'].'ekey/vn_len'$key_data['buf']);
        
$keys unpack('Vreserved/ve_len/a'.$keys['e_len'].'ekey/vn_len/a'.$keys['n_len'].'nkey'$key_data['buf']);
        return 
$keys;
    }


    
# sign data
    
public function Sign($data) {
        if (
$this->ekey == '' || $this->nkey == '') { die('Key is not loaded.'); }
        
WMXILogger::Append("$ekey = ".$this->ekey.";");
        
WMXILogger::Append("$nkey = ".$this->nkey.";");

        
$result '';
        
$plain $this->_md4($data);
        for(
$i 0$i 10; ++$i) { $plain .= pack('V'$this->debug mt_rand()); }
        
$plain pack('v'$this->_strlen($plain)).$plain;
        
$m $this->_hex2dec(bin2hex(strrev($plain)));
        
WMXILogger::Append("$m = $m;");
        
$a $this->_bcpowmod($m$this->ekey$this->nkey);
        
WMXILogger::Append("$a = $a;");
        
$result strtolower($this->_shortunswap($this->_dec2hex($a)));
        
WMXILogger::Append("$result = $result;");
        return 
$result;
    }


}


?>
Онлайн: 1
Реклама