modified 新增数据解密
This commit is contained in:
parent
220282c77c
commit
1bf2cf1efb
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
|
||||
namespace EasyTiktok\Kernel;
|
||||
|
||||
use EasyTiktok\Kernel\Exceptions\RuntimeException;
|
||||
use EasyTiktok\Kernel\Support\AES;
|
||||
|
||||
/**
|
||||
* Class Encryptor.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class Encryptor {
|
||||
public const ERROR_INVALID_SIGNATURE = -40001; // Signature verification failed
|
||||
public const ERROR_PARSE_XML = -40002; // Parse XML failed
|
||||
public const ERROR_CALC_SIGNATURE = -40003; // Calculating the signature failed
|
||||
public const ERROR_INVALID_AES_KEY = -40004; // Invalid AESKey
|
||||
public const ERROR_INVALID_APP_ID = -40005; // Check AppID failed
|
||||
public const ERROR_ENCRYPT_AES = -40006; // AES EncryptionInterface failed
|
||||
public const ERROR_DECRYPT_AES = -40007; // AES decryption failed
|
||||
public const ERROR_INVALID_XML = -40008; // Invalid XML
|
||||
public const ERROR_BASE64_ENCODE = -40009; // Base64 encoding failed
|
||||
public const ERROR_BASE64_DECODE = -40010; // Base64 decoding failed
|
||||
public const ERROR_XML_BUILD = -40011; // XML build failed
|
||||
public const ILLEGAL_BUFFER = -41003; // Illegal buffer
|
||||
|
||||
/**
|
||||
* App id.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $appId;
|
||||
|
||||
/**
|
||||
* App token.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $aesKey;
|
||||
|
||||
/**
|
||||
* Block size.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $blockSize = 32;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $appId
|
||||
* @param string|null $token
|
||||
* @param string|null $aesKey
|
||||
*/
|
||||
public function __construct(string $appId, string $token = null, string $aesKey = null) {
|
||||
$this->appId = $appId;
|
||||
$this->token = $token;
|
||||
$this->aesKey = base64_decode($aesKey . '=', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the app token.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getToken(): string {
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt message.
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $msgSignature
|
||||
* @param string $nonce
|
||||
* @param string $timestamp
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws RuntimeException|Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public function decrypt(string $content, string $msgSignature, string $nonce, string $timestamp): string {
|
||||
$signature = $this->signature($this->token, $timestamp, $nonce, $content);
|
||||
|
||||
if ($signature !== $msgSignature) {
|
||||
throw new RuntimeException('Invalid Signature.', self::ERROR_INVALID_SIGNATURE);
|
||||
}
|
||||
|
||||
$decrypted = AES::decrypt(
|
||||
base64_decode($content, true),
|
||||
$this->aesKey,
|
||||
substr($this->aesKey, 0, 16),
|
||||
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
|
||||
);
|
||||
$result = $this->pkcs7Unpad($decrypted);
|
||||
$content = substr($result, 16, strlen($result));
|
||||
$contentLen = unpack('N', substr($content, 0, 4))[1];
|
||||
|
||||
if (trim(substr($content, $contentLen + 4)) !== $this->appId) {
|
||||
throw new RuntimeException('Invalid appId.', self::ERROR_INVALID_APP_ID);
|
||||
}
|
||||
|
||||
return substr($content, 4, $contentLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SHA1.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function signature(): string {
|
||||
$array = func_get_args();
|
||||
sort($array, SORT_STRING);
|
||||
|
||||
return sha1(implode($array));
|
||||
}
|
||||
|
||||
/**
|
||||
* PKCS#7 pad.
|
||||
*
|
||||
* @param string $text
|
||||
* @param int $blockSize
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function pkcs7Pad(string $text, int $blockSize): string {
|
||||
if ($blockSize > 256) {
|
||||
throw new RuntimeException('$blockSize may not be more than 256');
|
||||
}
|
||||
$padding = $blockSize - (strlen($text) % $blockSize);
|
||||
$pattern = chr($padding);
|
||||
|
||||
return $text . str_repeat($pattern, $padding);
|
||||
}
|
||||
|
||||
/**
|
||||
* PKCS#7 unpad.
|
||||
*
|
||||
* @param string $text
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function pkcs7Unpad(string $text): string {
|
||||
$pad = ord(substr($text, -1));
|
||||
if ($pad < 1 || $pad > $this->blockSize) {
|
||||
$pad = 0;
|
||||
}
|
||||
|
||||
return substr($text, 0, (strlen($text) - $pad));
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ use EasyTiktok\Kernel\Traits\ResponseCastable;
|
|||
* @property Auth\AccessToken $access_token
|
||||
* @property Auth\Client $auth
|
||||
* @property QrCode\Client $qr_code
|
||||
* @property Server\Encryptor $encryptor
|
||||
* @author zhaoxiang <zhaoxiang051405@gmail.com>
|
||||
*/
|
||||
class Application extends ServiceContainer {
|
||||
|
@ -23,7 +24,8 @@ class Application extends ServiceContainer {
|
|||
protected $providers = [
|
||||
Base\ServiceProvider::class,
|
||||
Auth\ServiceProvider::class,
|
||||
QrCode\ServiceProvider::class
|
||||
QrCode\ServiceProvider::class,
|
||||
Server\ServiceProvider::class
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace EasyTiktok\MiniProgram\Server;
|
||||
|
||||
use EasyTiktok\Kernel\Encryptor as BaseEncryptor;
|
||||
use EasyTiktok\Kernel\Exceptions\DecryptException;
|
||||
use EasyTiktok\Kernel\Exceptions\InvalidArgumentException;
|
||||
use EasyTiktok\Kernel\Support\AES;
|
||||
|
||||
/**
|
||||
* Class Encryptor.
|
||||
*
|
||||
* @author mingyoung <mingyoungcheung@gmail.com>
|
||||
*/
|
||||
class Encryptor extends BaseEncryptor {
|
||||
/**
|
||||
* Decrypt data.
|
||||
*
|
||||
* @param string $sessionKey
|
||||
* @param string $iv
|
||||
* @param string $encrypted
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws DecryptException|InvalidArgumentException
|
||||
*/
|
||||
public function decryptData(string $sessionKey, string $iv, string $encrypted): array {
|
||||
$decrypted = AES::decrypt(
|
||||
base64_decode($encrypted, false),
|
||||
base64_decode($sessionKey, false),
|
||||
base64_decode($iv, false)
|
||||
);
|
||||
|
||||
$decrypted = json_decode($decrypted, true);
|
||||
|
||||
if (!$decrypted) {
|
||||
throw new DecryptException('The given payload is invalid.');
|
||||
}
|
||||
|
||||
return $decrypted;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace EasyTiktok\MiniProgram\Server;
|
||||
|
||||
use Pimple\Container;
|
||||
use Pimple\ServiceProviderInterface;
|
||||
|
||||
class ServiceProvider implements ServiceProviderInterface {
|
||||
/**
|
||||
* {@inheritdoc}.
|
||||
*/
|
||||
public function register(Container $pimple): void {
|
||||
!isset($pimple['encryptor']) && $pimple['encryptor'] = static function($app) {
|
||||
return new Encryptor(
|
||||
$app['config']['app_id'],
|
||||
$app['config']['token'],
|
||||
$app['config']['aes_key']
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue