$reply = generate_reply_message("success", $msg);
$encryptMsg = '';
$errCode = $pc->encryptMsg($reply, $nonce, $encryptMsg, $timeStamp);
function generate_reply_message($content, $receivedMsg) {
$xml = simplexml_load_string($receivedMsg, 'SimpleXMLElement', LIBXML_NOCDATA);
$toUserName = $xml->FromUserName;
$fromUserName = $xml->ToUserName;
$content = htmlspecialchars($content, ENT_QUOTES, 'UTF-8');
return "<xml>
<ToUserName><![CDATA[$toUserName]]></ToUserName>
<FromUserName><![CDATA[$fromUserName]]></FromUserName>
<CreateTime>" . time() . "</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[$content]]></Content>
</xml>";
}
public function encryptMsg($replyMsg, $nonce, &$encryptMsg, $timeStamp)
{
$logFilePath = __DIR__ . '';
$pc = new Prpcrypt($this->encodingAesKey);
$array = $pc->encrypt($replyMsg, $this->appId);
$ret = $array[0];
if ($ret != 0) {
error_log("Encryption failed. Error Code: $ret\n", 3, $logFilePath);
return $ret;
}
$encrypt = base64_encode($array[1]);
if ($timeStamp == null) {
$timeStamp = time();
}
$sha1 = new SHA1;
$array = $sha1->getSHA1($this->token, $timeStamp, $nonce, $encrypt);
$ret = $array[0];
if ($ret != 0) {
error_log("Signature generation failed. Error Code: $ret\n", 3, $logFilePath);
return $ret;
}
$signature = $array[1];
$xmlparse = new XMLParse;
$encryptMsg = $xmlparse->generate($encrypt, $signature, $timeStamp, $nonce);
return ErrorCode::$OK;
}
public function encrypt($text, $appid)
{
$logFilePath = __DIR__ . '';
try {
if (empty($appid)) {
error_log("AppId is empty. Please check the configuration or input.\n", 3, $logFilePath);
throw new Exception("AppId cannot be empty.");
}
$random = openssl_random_pseudo_bytes(16);
$text = $random . pack("N", strlen($text)) . $text . $appid;
error_log("FullStr: " . bin2hex($text) . "\n", 3, $logFilePath);
if (strlen($this->key) != 32) {
error_log("Invalid AES Key: Length is not 32.\n", 3, $logFilePath);
throw new Exception("Invalid AES Key: Length must be 32 bytes.");
}
$pkc_encoder = new PKCS7Encoder();
$text = $pkc_encoder->encode($text);
$iv = $random;
$encrypted = openssl_encrypt($text, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv);
if ($encrypted === false) {
error_log("Error: openssl_encrypt failed.\n", 3, $logFilePath);
throw new Exception("Encryption failed");
}
return array(ErrorCode::$OK, $iv . $encrypted);
} catch (Exception $e) {
error_log("Encryption Exception: " . $e->getMessage() . "\n", 3, $logFilePath);
return array(ErrorCode::$EncryptAESError, null);
}
}
public function generate($encrypt, $signature, $timestamp, $nonce)
{
$format = "<xml>
<Encrypt><![CDATA[%s]]></Encrypt>
<MsgSignature><![CDATA[%s]]></MsgSignature>
<TimeStamp>%s</TimeStamp>
<Nonce><![CDATA[%s]]></Nonce>
</xml>";
return sprintf(
$format,
htmlspecialchars($encrypt, ENT_QUOTES, 'UTF-8'),
htmlspecialchars($signature, ENT_QUOTES, 'UTF-8'),
$timestamp,
htmlspecialchars($nonce, ENT_QUOTES, 'UTF-8')
);
}
}
public function getSHA1($token, $timestamp, $nonce, $encrypt_msg)
{
$logFilePath = __DIR__ . '';
if (empty($token) || empty($timestamp) || empty($nonce) || empty($encrypt_msg)) {
error_log("Error: Invalid parameters for SHA1 generation.\n", 3, $logFilePath);
return array(ErrorCode::$InvalidParameter, null);
}
try {
$timestamp = (string)$timestamp;
$nonce = (string)$nonce;
$token = (string)$token;
$encrypt_msg = (string)$encrypt_msg;
$array = [$token, $timestamp, $nonce, $encrypt_msg];
sort($array, SORT_STRING);
$str = implode('', $array);
$signature = sha1($str);
return array(ErrorCode::$OK, $signature);
} catch (Exception $e) {
error_log("SHA1 generation failed: " . $e->getMessage() . "\n", 3, $logFilePath);
return array(ErrorCode::$ComputeSignatureError, null);
}
}
import base64
import hashlib
from Crypto.Cipher import AES
import struct
def verify_signature(token, encrypt, timestamp, nonce, msg_signature):
"""
验证消息签名是否正确
"""
params = sorted([encrypt, nonce, timestamp, token])
sorted_str = ''.join(params)
sha1 = hashlib.sha1()
sha1.update(sorted_str.encode('utf-8'))
calculated_signature = sha1.hexdigest()
print(f"[签名验证] 计算签名: {calculated_signature}")
print(f"[签名验证] 收到签名: {msg_signature}")
return calculated_signature == msg_signature
def decrypt_message(encoding_aes_key, encrypt):
"""
执行AES解密并解析明文
"""
try:
aes_key = base64.b64decode(encoding_aes_key + "==")
if len(aes_key) != 32:
print(f"[错误] AESKey长度不正确: {len(aes_key)}字节,应为32字节")
return None
encrypt = encrypt.replace('-', '+').replace('_', '/')
encrypted_data = base64.b64decode(encrypt)
print(f"[解密] Base64解码后数据长度: {len(encrypted_data)}字节")
iv = encrypted_data[:16]
ciphertext = encrypted_data[16:]
print(f"[解密] IV(HEX): {iv.hex()}")
cipher = AES.new(aes_key, AES.MODE_CBC, iv=iv)
decrypted = cipher.decrypt(ciphertext)
pad = decrypted[-1]
decrypted = decrypted[:-pad]
print(f"[解密] 去除填充后长度: {len(decrypted)}字节")
random = decrypted[:16]
msg_len = struct.unpack('>I', decrypted[16:20])[0]
msg = decrypted[20:20+msg_len].decode('utf-8')
appid = decrypted[20+msg_len:].decode('utf-8')
print("\n======= 解密结果 =======")
print(f"Random(HEX): {random.hex()}")
print(f"消息长度: {msg_len}字节")
print(f"消息内容: {msg}")
print(f"AppID: {appid}")
print("=======================")
return msg
except Exception as e:
print(f"[错误] 解密过程中发生异常: {str(e)}")
return None
if __name__ == "__main__":
encrypt = ""
timestamp = ""
nonce = ""
msg_signature = ""
token = ""
encoding_aes_key = ""
print("===== 开始签名验证 =====")
if verify_signature(token, encrypt, timestamp, nonce, msg_signature):
print("\n===== 签名验证通过,开始解密 =====")
decrypt_message(encoding_aes_key, encrypt)
else:
print("\n[错误] 签名验证失败,终止处理")
你好,提供下appid和时间点