http://www.zhaoyuanma.com/
<?php
define ( "DES_KEY", "SCUBEPGW" );
define ( "HASH_PAD", "0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414" );
bcscale ( 0 );
$private_key = array ();
// 兼容 php5.4+
if (! function_exists ( 'hex2bin' )) {
function hex2bin($hexdata) {
$bindata = '';
if (strlen ( $hexdata ) % 2 == 1) {
$hexdata = '0' . $hexdata;
}
for($i = 0; $i < strlen ( $hexdata ); $i += 2) {
$bindata .= chr ( hexdec ( substr ( $hexdata, $i, 2 ) ) );
}
return $bindata;
}
}
function padstr($src, $len = 256, $chr = '0', $d = 'L') {
$ret = trim ( $src );
$padlen = $len - strlen ( $ret );
if ($padlen > 0) {
$pad = str_repeat ( $chr, $padlen );
if (strtoupper ( $d ) == 'L') {
$ret = $pad . $ret;
} else {
$ret = $ret . $pad;
}
}
return $ret;
}
function bin2int($bindata) {
$hexdata = bin2hex ( $bindata );
return bchexdec ( $hexdata );
}
function bchexdec($hexdata) {
$ret = '0';
$len = strlen ( $hexdata );
for($i = 0; $i < $len; $i ++) {
$hex = substr ( $hexdata, $i, 1 );
$dec = hexdec ( $hex );
$exp = $len - $i - 1;
$pow = bcpow ( '16', $exp );
$tmp = bcmul ( $dec, $pow );
$ret = bcadd ( $ret, $tmp );
}
return $ret;
}
function bcdechex($decdata) {
$s = $decdata;
$ret = '';
while ( $s != '0' ) {
$m = bcmod ( $s, '16' );
$s = bcdiv ( $s, '16' );
$hex = dechex ( $m );
$ret = $hex . $ret;
}
return $ret;
}
function sha1_128($string) {
$hash = sha1 ( $string );
$sha_bin = hex2bin ( $hash );
$sha_pad = hex2bin ( HASH_PAD );
return $sha_pad . $sha_bin;
}
function mybcpowmod($num, $pow, $mod) {
if (function_exists ( 'bcpowmod' )) {
return bcpowmod ( $num, $pow, $mod );
}
return emubcpowmod ( $num, $pow, $mod );
}
function emubcpowmod($num, $pow, $mod) {
$result = '1';
do {
if (! bccomp ( bcmod ( $pow, '2' ), '1' )) {
$result = bcmod ( bcmul ( $result, $num ), $mod );
}
$num = bcmod ( bcpow ( $num, '2' ), $mod );
$pow = bcdiv ( $pow, '2' );
} while ( bccomp ( $pow, '0' ) );
return $result;
}
function rsa_encrypt($private_key, $input) {
$p = bin2int ( $private_key ["prime1"] );
$q = bin2int ( $private_key ["prime2"] );
$u = bin2int ( $private_key ["coefficient"] );
$dP = bin2int ( $private_key ["prime_exponent1"] );
$dQ = bin2int ( $private_key ["prime_exponent2"] );
$c = bin2int ( $input );
$cp = bcmod ( $c, $p );
$cq = bcmod ( $c, $q );
$a = mybcpowmod ( $cp, $dP, $p );
$b = mybcpowmod ( $cq, $dQ, $q );
if (bccomp ( $a, $b ) >= 0) {
$result = bcsub ( $a, $b );
} else {
$result = bcsub ( $b, $a );
$result = bcsub ( $p, $result );
}
$result = bcmod ( $result, $p );
$result = bcmul ( $result, $u );
$result = bcmod ( $result, $p );
$result = bcmul ( $result, $q );
$result = bcadd ( $result, $b );
$ret = bcdechex ( $result );
$ret = strtoupper ( padstr ( $ret ) );
return (strlen ( $ret ) == 256) ? $ret : false;
}
function rsa_decrypt($input) {
global $private_key;
$check = bchexdec ( $input );
$modulus = bin2int ( $private_key ["modulus"] );
$exponent = bchexdec ( "010001" );
$result = bcpowmod ( $check, $exponent, $modulus );
$rb = bcdechex ( $result );
return strtoupper ( padstr ( $rb ) );
}
function buildKey($key) {
global $private_key;
if (count ( $private_key ) > 0) {
foreach ( $private_key as $name => $value ) {
unset ( $private_key [$name] );
}
}
$ret = false;
$key_file = parse_ini_file ( $key );
if (! $key_file) {
return $ret;
}
$hex = "";
if (array_key_exists ( "MERID", $key_file )) {
$ret = $key_file ["MERID"];
$private_key ["MERID"] = $ret;
$hex = substr ( $key_file ["prikeyS"], 80 );
} else if (array_key_exists ( "PGID", $key_file )) {
$ret = $key_file ["PGID"];
$private_key ["PGID"] = $ret;
$hex = substr ( $key_file ["pubkeyS"], 48 );
} else {
return $ret;
}
$bin = hex2bin ( $hex );
$private_key ["modulus"] = substr ( $bin, 0, 128 );
$cipher = MCRYPT_DES;
$iv = str_repeat ( "x00", 8 );
$prime1 = substr ( $bin, 384, 64 );
// 兼容 php5.5+
// $enc = mcrypt_cbc ( $cipher, DES_KEY, $prime1, MCRYPT_DECRYPT, $iv );
$enc = mcrypt_decrypt ( $cipher, DES_KEY, $prime1, 'cbc', $iv );
$private_key ["prime1"] = $enc;
$prime2 = substr ( $bin, 448, 64 );
// $enc = mcrypt_cbc ( $cipher, DES_KEY, $prime2, MCRYPT_DECRYPT, $iv );
$enc = mcrypt_decrypt ( $cipher, DES_KEY, $prime2, 'cbc', $iv );
$private_key ["prime2"] = $enc;
$prime_exponent1 = substr ( $bin, 512, 64 );
// $enc = mcrypt_cbc ( $cipher, DES_KEY, $prime_exponent1, MCRYPT_DECRYPT,
// $iv );
$enc = mcrypt_decrypt ( $cipher, DES_KEY, $prime_exponent1, 'cbc', $iv );
$private_key ["prime_exponent1"] = $enc;
$prime_exponent2 = substr ( $bin, 576, 64 );
// $enc = mcrypt_cbc ( $cipher, DES_KEY, $prime_exponent2, MCRYPT_DECRYPT,
// $iv );
$enc = mcrypt_decrypt ( $cipher, DES_KEY, $prime_exponent2, 'cbc', $iv );
$private_key ["prime_exponent2"] = $enc;
$coefficient = substr ( $bin, 640, 64 );
// $enc = mcrypt_cbc ( $cipher, DES_KEY, $coefficient, MCRYPT_DECRYPT, $iv
// );
$enc = mcrypt_decrypt ( $cipher, DES_KEY, $coefficient, 'cbc', $iv );
$private_key ["coefficient"] = $enc;
return $ret;
}
function sign($msg) {
global $private_key;
if (! array_key_exists ( "MERID", $private_key )) {
return false;
}
$hb = sha1_128 ( $msg );
return rsa_encrypt ( $private_key, $hb );
}
function signOrder($merid, $ordno, $amount, $curyid, $transdate, $transtype) {
if (strlen ( $merid ) != 15)
return false;
if (strlen ( $ordno ) != 16)
return false;
if (strlen ( $amount ) != 12)
return false;
if (strlen ( $curyid ) != 3)
return false;
if (strlen ( $transdate ) != 8)
return false;
if (strlen ( $transtype ) != 4)
return false;
$plain = $merid . $ordno . $amount . $curyid . $transdate . $transtype;
return sign ( $plain );
}
function verify($plain, $check) {
global $private_key;
if (! array_key_exists ( "PGID", $private_key )) {
return false;
}
if (strlen ( $check ) != 256) {
return false;
}
$hb = sha1_128 ( $plain );
$hbhex = strtoupper ( bin2hex ( $hb ) );
$rbhex = rsa_decrypt ( $check );
return $hbhex == $rbhex ? true : false;
}
function verifyTransResponse($merid, $ordno, $amount, $curyid, $transdate, $transtype, $ordstatus, $check) {
if (strlen ( $merid ) != 15)
return false;
if (strlen ( $ordno ) != 16)
return false;
if (strlen ( $amount ) != 12)
return false;
if (strlen ( $curyid ) != 3)
return false;
if (strlen ( $transdate ) != 8)
return false;
if (strlen ( $transtype ) != 4)
return false;
if (strlen ( $ordstatus ) != 4)
return false;
if (strlen ( $check ) != 256)
return false;
$plain = $merid . $ordno . $amount . $curyid . $transdate . $transtype . $ordstatus;
return verify ( $plain, $check );
}