Skip to content

Commit

Permalink
增加XML类和 删除mcrypt函数更换为openssl
Browse files Browse the repository at this point in the history
  • Loading branch information
tianye committed Aug 29, 2017
1 parent 5c6abc4 commit 36ea0a6
Show file tree
Hide file tree
Showing 2 changed files with 248 additions and 44 deletions.
151 changes: 107 additions & 44 deletions src/Core/WechatCode/Prpcrypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

namespace OpenOauth\Core\WechatCode;

use OpenOauth\Core\WechatCode\ErrorCode;
use OpenOauth\Core\WechatCode\Pkcs7Encoder;
use Exception;
use OpenOauth\Core\XML;


/**
* Prpcrypt class
Expand All @@ -12,38 +13,36 @@
*/
class Prpcrypt
{
public $key;
protected $AESKey;
protected $blockSize;

public function __construct($k)
{
$this->key = base64_decode($k . "=");
$this->AESKey = $k;

$this->blockSize = 32;
}

/**
* 对明文进行加密
*
* @param string $text 需要加密的明文
*
* @return string 加密后的密文
* @param string $appId
*
* @return array
*/
public function encrypt($text, $appid)
public function encrypt($text, $appId)
{
try {
//获得16位随机字符串,填充到明文之前
$key = $this->getAESKey();
$random = $this->getRandomStr();
$text = $random . pack("N", strlen($text)) . $text . $appid;
// 网络字节序
$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$iv = substr($this->key, 0, 16);
//使用自定义的填充方式对明文进行补位填充
$pkc_encoder = new PKCS7Encoder;
$text = $pkc_encoder->encode($text);
mcrypt_generic_init($module, $this->key, $iv);
//加密
$encrypted = mcrypt_generic($module, $text);
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
$text = $this->encode($random . pack('N', strlen($text)) . $text . $appId);

$iv = substr($key, 0, 16);

$encrypted = openssl_encrypt($text, 'aes-256-cbc', $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv);

//print(base64_encode($encrypted));
//使用BASE64对加密后的字符串进行编码
Expand All @@ -55,51 +54,52 @@ public function encrypt($text, $appid)
}

/**
* 对密文进行解密
*
* @param string $encrypted 需要解密的密文
* @param string $appId APPID
*
* @return string 解密得到的明文
* @return array|string
*/
public function decrypt($encrypted, $appid)
public function decrypt($encrypted, $appId)
{
try {
//使用BASE64对需要解密的字符串进行解码
$ciphertext_dec = base64_decode($encrypted);
$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$iv = substr($this->key, 0, 16);
mcrypt_generic_init($module, $this->key, $iv);

//解密
$decrypted = mdecrypt_generic($module, $ciphertext_dec);
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
$key = $this->getAESKey();
$ciphertext = base64_decode($encrypted, true);
$iv = substr($key, 0, 16);

$decrypted = openssl_decrypt($ciphertext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv);
} catch (Exception $e) {
return [ErrorCode::$DecryptAESError, null];
}

try {
//去除补位字符
$pkc_encoder = new PKCS7Encoder;
$result = $pkc_encoder->decode($decrypted);
//去除16位随机字符串,网络字节序和AppId
$result = $this->decode($decrypted);

if (strlen($result) < 16) {
return "";
return '';
}
$content = substr($result, 16, strlen($result));
$len_list = unpack("N", substr($content, 0, 4));
$xml_len = $len_list[1];
$xml_content = substr($content, 4, $xml_len);
$from_appid = substr($content, $xml_len + 4);

$content = substr($result, 16, strlen($result));
$listLen = unpack('N', substr($content, 0, 4));
$xmlLen = $listLen[1];
$xml = substr($content, 4, $xmlLen);
$fromAppId = trim(substr($content, $xmlLen + 4));
} catch (Exception $e) {
//print $e;
return [ErrorCode::$IllegalBuffer, null];
}
if ($from_appid != $appid) {
if ($fromAppId !== $appId) {
return [ErrorCode::$ValidateAppidError, null];
}

return [0, $xml_content];
$dataSet = json_decode($xml, true);
if ($dataSet && (JSON_ERROR_NONE === json_last_error())) {
// For mini-program JSON formats.
// Convert to XML if the given string can be decode into a data array.
$xml = XML::build($dataSet);
}

return [ErrorCode::$OK, $xml];
}

/**
Expand All @@ -118,4 +118,67 @@ public function getRandomStr()

return $str;
}

/**
* Return AESKey.
*
* @return string
*
* @throws Exception
*/
protected function getAESKey()
{
if (empty($this->AESKey)) {
throw new Exception("Configuration mission, 'aes_key' is required.");
}

if (strlen($this->AESKey) !== 43) {
throw new Exception("The length of 'aes_key' must be 43.");
}

return base64_decode($this->AESKey . '=', true);
}

/**
* Decode string.
*
* @param string $decrypted
*
* @return string
*/
public function decode($decrypted)
{
$pad = ord(substr($decrypted, -1));

if ($pad < 1 || $pad > $this->blockSize) {
$pad = 0;
}

return substr($decrypted, 0, (strlen($decrypted) - $pad));
}

/**
* Encode string.
*
* @param string $text
*
* @return string
*/
public function encode($text)
{
$padAmount = $this->blockSize - (strlen($text) % $this->blockSize);

$padAmount = $padAmount !== 0 ? $padAmount : $this->blockSize;

$padChr = chr($padAmount);

$tmp = '';

for ($index = 0; $index < $padAmount; ++$index) {
$tmp .= $padChr;
}

return $text . $tmp;
}

}
141 changes: 141 additions & 0 deletions src/Core/XML.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

namespace OpenOauth\Core;

/**
* XML.php.
*/
use SimpleXMLElement;

/**
* Class XML.
*/
class XML
{
/**
* XML to array.
*
* @param string $xml XML string
*
* @return array|\SimpleXMLElement
*/
public static function parse($xml)
{
return self::normalize(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS));
}

/**
* XML encode.
*
* @param mixed $data
* @param string $root
* @param string $item
* @param string $attr
* @param string $id
*
* @return string
*/
public static function build(
$data,
$root = 'xml',
$item = 'item',
$attr = '',
$id = 'id'
)
{
if (is_array($attr)) {
$_attr = [];

foreach ($attr as $key => $value) {
$_attr[] = "{$key}=\"{$value}\"";
}

$attr = implode(' ', $_attr);
}

$attr = trim($attr);
$attr = empty($attr) ? '' : " {$attr}";
$xml = "<{$root}{$attr}>";
$xml .= self::data2Xml($data, $item, $id);
$xml .= "</{$root}>";

return $xml;
}

/**
* Build CDATA.
*
* @param string $string
*
* @return string
*/
public static function cdata($string)
{
return sprintf('<![CDATA[%s]]>', $string);
}

/**
* Object to array.
*
*
* @param SimpleXMLElement $obj
*
* @return array
*/
protected static function normalize($obj)
{
$result = null;

if (is_object($obj)) {
$obj = (array) $obj;
}

if (is_array($obj)) {
foreach ($obj as $key => $value) {
$res = self::normalize($value);
if (($key === '@attributes') && ($key)) {
$result = $res;
} else {
$result[$key] = $res;
}
}
} else {
$result = $obj;
}

return $result;
}

/**
* Array to XML.
*
* @param array $data
* @param string $item
* @param string $id
*
* @return string
*/
protected static function data2Xml($data, $item = 'item', $id = 'id')
{
$xml = $attr = '';

foreach ($data as $key => $val) {
if (is_numeric($key)) {
$id && $attr = " {$id}=\"{$key}\"";
$key = $item;
}

$xml .= "<{$key}{$attr}>";

if ((is_array($val) || is_object($val))) {
$xml .= self::data2Xml((array) $val, $item, $id);
} else {
$xml .= is_numeric($val) ? $val : self::cdata($val);
}

$xml .= "</{$key}>";
}

return $xml;
}
}

0 comments on commit 36ea0a6

Please sign in to comment.