您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
提供沙箱内的 DeepQuery API,自动签名并与页面核心通信。可 @require 于任意调用脚本顶部。
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyforks.org/scripts/548365/1654735/DeepQuery%20Secure%20Client%20%28sandbox%29.js
// ==UserScript== // @name DeepQuery Secure Client (sandbox) // @namespace dq.secure.v2.client // @version 2.0.0 // @description 提供沙箱内的 DeepQuery API,自动签名并与页面核心通信。可 @require 于任意调用脚本顶部。 // @author you // @match http://*/* // @match https://*/* // @include about:blank // @run-at document-start // @grant none // ==/UserScript== (function () { 'use strict'; /******** 配置:必须与 Core 一致 ********/ const CHANNEL = '__DQ_SECURE_V2__'; // ★★★ 重要:把下面的 KEY_PARTS 替换成你自己的一组(与 Core 完全一致) ★★★ const KEY_PARTS = [ 'dW5hcmFuZG9tLWtleS1zZWVkLQ', 'tZXBsZWFzZS1yZXBsYWNlLW1l', 'LXdpdGgtYS1wcm9wZXItb25l' ]; // 是否在本沙箱里提供一个 top.DeepQuery 代理(零改动用) const EXPOSE_TOP_PROXY = false; const te = new TextEncoder(); function b64ToU8(b64) { const pad = b64.length % 4 ? (4 - b64.length % 4) : 0; const s = b64 + '='.repeat(pad); const bin = atob(s.replace(/-/g, '+').replace(/_/g, '/')); const u8 = new Uint8Array(bin.length); for (let i = 0; i < bin.length; i++) u8[i] = bin.charCodeAt(i); return u8; } const KEY_U8 = b64ToU8(KEY_PARTS.join('')); async function sha256U8(u8) { const buf = await crypto.subtle.digest('SHA-256', u8); return new Uint8Array(buf); } async function hmacSignRaw(key, u8) { const k = await crypto.subtle.importKey( 'raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'] ); const sig = await crypto.subtle.sign('HMAC', k, u8); return new Uint8Array(sig); } const pending = new Map(); function rid() { return (Date.now().toString(36) + Math.random().toString(36).slice(2, 10)).toUpperCase(); } function send(payload) { window.top.postMessage({ [CHANNEL]: payload }, '*'); } window.addEventListener('message', (e) => { const msg = e.data && e.data[CHANNEL]; if (!msg || msg.cmd !== 'RESP' || !msg.id) return; const hit = pending.get(msg.id); if (!hit) return; pending.delete(msg.id); hit.resolve(msg.res); }, false); async function request(spec) { const id = rid(); const ts = Date.now(); const nonce = rid() + Math.random().toString(36).slice(2); const payload = te.encode(id + '\n' + ts + '\n' + nonce + '\n'); const bodyHash = await sha256U8(te.encode(JSON.stringify(spec || {}))); const toSign = new Uint8Array(payload.length + bodyHash.length); toSign.set(payload, 0); toSign.set(bodyHash, payload.length); const sigU8 = await hmacSignRaw(KEY_U8, toSign); const sigB64 = btoa(String.fromCharCode(...sigU8)); return new Promise((resolve) => { pending.set(id, { resolve }); send({ cmd: 'REQ', id, ts, nonce, sigB64, spec }); // 可选超时(以 spec.timeout 为基准) const timeout = typeof spec.timeout === 'number' ? Math.max(200, spec.timeout + 500) : 6000; setTimeout(() => { if (pending.has(id)) { pending.delete(id); resolve({ ok: false, error: 'TIMEOUT' }); } }, timeout); }); } // 暴露与旧版一致的方法 const DeepQuery = { async get(spec = {}) { return request(spec); }, async attr({ framePath, chain, name, timeout }) { return request({ framePath, chain, timeout, pick: { attr: name } }); }, async prop({ framePath, chain, name, timeout }) { return request({ framePath, chain, timeout, pick: { prop: name } }); }, async text({ framePath, chain, timeout }) { return request({ framePath, chain, timeout, pick: { text: true } }); }, async html({ framePath, chain, timeout }) { return request({ framePath, chain, timeout, pick: { html: true } }); }, async rect({ framePath, chain, timeout }) { return request({ framePath, chain, timeout, pick: { rect: true } }); }, version: '2.0.0-client' }; // 方式 A:推荐 —— 在沙箱里直接提供全局 DeepQuery try { window.DeepQuery = DeepQuery; } catch {} // 方式 B:零改动(仅本沙箱可见的 top.DeepQuery 代理) if (EXPOSE_TOP_PROXY) { try { // 注意:这个属性只存在于当前 userscript 的沙箱 proxy 上,页面/其它沙箱看不到 Object.defineProperty(window.top, 'DeepQuery', { configurable: true, get() { return DeepQuery; } }); } catch {} } try { console.debug('[DeepQuery Secure Client] ready'); } catch {} })();