diff --git a/app/Module/Doo.php b/app/Module/Doo.php index 30000a508..fcf85b2a9 100644 --- a/app/Module/Doo.php +++ b/app/Module/Doo.php @@ -398,9 +398,22 @@ class Doo } } if ($array['client_type'] === 'pgp' && $array['client_key']) { - $array['client_key'] = str_replace(["-", "_", "$"], ["+", "/", "\n"], $array['client_key']); - $array['client_key'] = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n" . $array['client_key'] . "\n-----END PGP PUBLIC KEY BLOCK-----"; + $array['client_key'] = self::pgpPublicFormat($array['client_key']); } return $array; } + + /** + * 还原公钥格式 + * @param $key + * @return string + */ + public static function pgpPublicFormat($key): string + { + $key = str_replace(["-", "_", "$"], ["+", "/", "\n"], $key); + if (!str_contains($key, '-----BEGIN PGP PUBLIC KEY BLOCK-----')) { + $key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n" . $key . "\n-----END PGP PUBLIC KEY BLOCK-----"; + } + return $key; + } } diff --git a/app/Services/WebSocketService.php b/app/Services/WebSocketService.php index f03159606..8b95b46cd 100644 --- a/app/Services/WebSocketService.php +++ b/app/Services/WebSocketService.php @@ -138,6 +138,16 @@ class WebSocketService implements WebSocketHandlerInterface } } return; + + /** + * 加密参数 + */ + case 'encrypt': + if ($data['type'] === 'pgp') { + $data['key'] = Doo::pgpPublicFormat($data['key']); + } + Cache::put("User::encrypt:" . $frame->fd, Base::array2json($data), Carbon::now()->addDay()); + return; } // if ($msgId) { diff --git a/app/Tasks/PushTask.php b/app/Tasks/PushTask.php index 52933dffe..a10e9bc6a 100644 --- a/app/Tasks/PushTask.php +++ b/app/Tasks/PushTask.php @@ -6,6 +6,7 @@ namespace App\Tasks; use App\Models\WebSocket; use App\Models\WebSocketTmpMsg; use App\Module\Base; +use App\Module\Doo; use Cache; use Carbon\Carbon; use Hhxsv5\LaravelS\Swoole\Task\Task; @@ -177,10 +178,19 @@ class PushTask extends AbstractTask Task::deliver($task); } else { try { + $encrypt = Base::json2array(Cache::get("User::encrypt:" . $fid)); + if ($encrypt['type'] == 'pgp') { + $msg = [ + 'type' => 'encrypt', + 'encrypted' => Doo::pgpEncryptApi($msg, $encrypt['key']), + ]; + } $swoole->push($fid, Base::array2json($msg)); - $tmpMsgId > 0 && WebSocketTmpMsg::whereId($tmpMsgId)->update(['send' => 1]); + if ($tmpMsgId > 0) { + WebSocketTmpMsg::whereId($tmpMsgId)->update(['send' => 1]); + } } catch (\Throwable) { - + // 发送失败 } } } diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 5bb120357..56b44d92a 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -151,7 +151,7 @@ export default { params.data = {encrypted: await dispatch("pgpEncryptApi", params.data)} } } - encrypt.push("client_type=pgp;client_key=" + $urlSafe((await dispatch("pgpGetLocalKey")).publicKeyB64)) + encrypt.push("client_type=pgp;client_key=" + (await dispatch("pgpGetLocalKey")).publicKeyB64) } if (encrypt.length > 0) { params.header.encrypt = encrypt.join(";") @@ -2843,11 +2843,19 @@ export default { state.wsRandom = wsRandom; // state.ws = new WebSocket(url); - state.ws.onopen = (e) => { + state.ws.onopen = async (e) => { wgLog && console.log("[WS] Open", e, $A.formatDate()) state.wsOpenNum++; + // + dispatch("websocketSend", { + type: 'encrypt', + data: { + type: 'pgp', + key: (await dispatch("pgpGetLocalKey")).publicKeyB64 + } + }) }; - state.ws.onclose = (e) => { + state.ws.onclose = async (e) => { wgLog && console.log("[WS] Close", e, $A.formatDate()) state.ws = null; // @@ -2856,7 +2864,7 @@ export default { wsRandom === state.wsRandom && dispatch('websocketConnection'); }, 3000); }; - state.ws.onerror = (e) => { + state.ws.onerror = async (e) => { wgLog && console.log("[WS] Error", e, $A.formatDate()) state.ws = null; // @@ -2865,9 +2873,13 @@ export default { wsRandom === state.wsRandom && dispatch('websocketConnection'); }, 3000); }; - state.ws.onmessage = (e) => { + state.ws.onmessage = async (e) => { wgLog && console.log("[WS] Message", e); - const msgDetail = $A.formatMsgBasic($A.jsonParse(e.data)); + let result = $A.jsonParse(e.data); + if (result.type === "encrypt" && result.encrypted) { + result = await dispatch("pgpDecryptApi", result.encrypted) + } + const msgDetail = $A.formatMsgBasic(result); const {type, msgId} = msgDetail; switch (type) { case "open": @@ -3203,7 +3215,7 @@ export default { passphrase: state.clientId, userIDs: [{name: 'doo', email: 'admin@admin.com'}], }) - data.publicKeyB64 = data.publicKey.replace(/\s*-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----\s*/g, '').replace(/\n+/g, '$') + data.publicKeyB64 = $urlSafe(data.publicKey.replace(/\s*-----(BEGIN|END) PGP PUBLIC KEY BLOCK-----\s*/g, '')) resolve(data) }) }, diff --git a/resources/assets/js/store/utils.js b/resources/assets/js/store/utils.js index 6ce7f8637..6c4d560d9 100644 --- a/resources/assets/js/store/utils.js +++ b/resources/assets/js/store/utils.js @@ -77,9 +77,9 @@ export function $callData(key, requestData, state) { export function $urlSafe(value, encode = true) { if (value) { if (encode) { - value = String(value).replace(/\+/g, "-").replace(/\//g, "_") + value = String(value).replace(/\+/g, "-").replace(/\//g, "_").replace(/\n/g, '$') } else { - value = String(value).replace(/-/g, "+").replace(/_/g, "/") + value = String(value).replace(/\-/g, "+").replace(/\_/g, "/").replace(/\$/g, '\n') } } return value