197 lines
6.5 KiB
JavaScript
197 lines
6.5 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { describe, it } from "node:test";
|
|
import {
|
|
buildProfileReport,
|
|
networkDiagnosticsToFacts,
|
|
stableHash,
|
|
summarizeExposureForRecording,
|
|
} from "../src/superFingerprint.mjs";
|
|
import { getMessages } from "../src/i18n.mjs";
|
|
|
|
describe("super fingerprint profile", () => {
|
|
it("hashes high-entropy values deterministically without echoing the source", () => {
|
|
const first = stableHash("canvas-renderer-fingerprint-value");
|
|
const second = stableHash("canvas-renderer-fingerprint-value");
|
|
|
|
assert.equal(first, second);
|
|
assert.match(first, /^[a-f0-9]{12}$/);
|
|
assert.notEqual(first, "canvas-renderer-fingerprint-value");
|
|
});
|
|
|
|
it("summarizes staged facts for recording without leaking raw high-entropy values", () => {
|
|
const signals = summarizeExposureForRecording("local", [
|
|
{
|
|
id: "canvas-hash",
|
|
category: "graphics",
|
|
label: "Canvas 指纹",
|
|
value: "canvas-secret-hash-abc123",
|
|
inference: "可作为跨站稳定识别材料",
|
|
sensitivity: "high",
|
|
},
|
|
{
|
|
id: "precise-location",
|
|
category: "permission",
|
|
label: "定位坐标",
|
|
value: "31.2304,121.4737",
|
|
inference: "授权后可得到精确位置",
|
|
sensitivity: "critical",
|
|
},
|
|
{
|
|
id: "screen",
|
|
category: "device",
|
|
label: "屏幕",
|
|
value: "1512x982@2",
|
|
inference: "可推断设备档位",
|
|
sensitivity: "medium",
|
|
},
|
|
]);
|
|
const raw = signals.map((signal) => signal.raw).join(" ");
|
|
|
|
assert.equal(signals.length, 2);
|
|
assert.match(raw, /stage=local/);
|
|
assert.match(raw, /facts=3/);
|
|
assert.match(raw, /high=1/);
|
|
assert.match(raw, /critical=1/);
|
|
assert.doesNotMatch(raw, /canvas-secret-hash/);
|
|
assert.doesNotMatch(raw, /31\.2304/);
|
|
assert.doesNotMatch(raw, /121\.4737/);
|
|
});
|
|
|
|
it("turns server request diagnostics into explainable facts", () => {
|
|
const facts = networkDiagnosticsToFacts({
|
|
server: {
|
|
observedIp: "198.51.100.24",
|
|
forwardedFor: "203.0.113.42",
|
|
cfConnectingIp: "198.51.100.25",
|
|
realIpHeader: null,
|
|
geoIp: {
|
|
city: {
|
|
available: true,
|
|
found: true,
|
|
countryCode: "US",
|
|
region: "California",
|
|
city: "Los Angeles",
|
|
latitude: 34.05,
|
|
longitude: -118.24,
|
|
},
|
|
asn: {
|
|
available: true,
|
|
found: true,
|
|
asn: 15169,
|
|
organization: "Google LLC",
|
|
},
|
|
},
|
|
},
|
|
webrtc: { summary: { total: 2, public: 1, private: 0, mdns: 1 } },
|
|
connection: { supported: true, effectiveType: "4g", downlink: 10, rtt: 40, saveData: false },
|
|
});
|
|
|
|
assert.equal(facts.some((fact) => fact.id === "server-observed-ip"), true);
|
|
assert.equal(facts.some((fact) => fact.id === "request-forwarded-for"), true);
|
|
assert.equal(facts.some((fact) => fact.id === "webrtc-candidates"), true);
|
|
assert.equal(facts.some((fact) => fact.id === "ip-database-city"), true);
|
|
assert.equal(facts.some((fact) => fact.id === "ip-database-asn"), true);
|
|
assert.match(facts.map((fact) => fact.value).join(" "), /198\.51\.100\.24/);
|
|
assert.match(facts.map((fact) => fact.value).join(" "), /Los Angeles/);
|
|
});
|
|
|
|
it("builds a readable staged report from passive, advanced, permission, and network data", () => {
|
|
const report = buildProfileReport({
|
|
generatedAt: "2026-07-03T10:00:00.000Z",
|
|
regionResult: { score: 72, band: "high" },
|
|
passiveFacts: [
|
|
{
|
|
id: "timezone",
|
|
category: "identity",
|
|
label: "系统时区",
|
|
value: "Asia/Shanghai",
|
|
inference: "地区倾向较强",
|
|
sensitivity: "medium",
|
|
},
|
|
],
|
|
requestFacts: [
|
|
{
|
|
id: "server-observed-ip",
|
|
category: "request",
|
|
label: "服务端连接地址",
|
|
value: "127.0.0.1",
|
|
inference: "后端从这次请求连接中看到的来源地址",
|
|
sensitivity: "high",
|
|
},
|
|
],
|
|
permissionFacts: [
|
|
{
|
|
id: "geolocation",
|
|
category: "permission",
|
|
label: "定位授权",
|
|
value: "未授权",
|
|
inference: "用户尚未授予定位权限",
|
|
sensitivity: "critical",
|
|
},
|
|
],
|
|
networkDiagnostics: {
|
|
server: { observedIp: "127.0.0.1" },
|
|
webrtc: { summary: { total: 2, public: 0, private: 0, mdns: 2 } },
|
|
},
|
|
});
|
|
|
|
assert.match(report, /浏览器暴露画像报告/);
|
|
assert.match(report, /第一阶段:本地画像/);
|
|
assert.match(report, /第二阶段:加上后端请求/);
|
|
assert.match(report, /授权后新增信息/);
|
|
assert.match(report, /服务端看到的地址: 127\.0\.0\.1/);
|
|
});
|
|
|
|
it("localizes the staged report with translated fact labels", () => {
|
|
const report = buildProfileReport(
|
|
{
|
|
generatedAt: "2026-07-03T10:00:00.000Z",
|
|
regionResult: { score: 72, band: "high" },
|
|
passiveFacts: [
|
|
{
|
|
id: "timezone",
|
|
category: "identity",
|
|
label: "系统时区",
|
|
value: "Asia/Shanghai",
|
|
inference: "可推断所在时区和常见地区。",
|
|
sensitivity: "medium",
|
|
},
|
|
],
|
|
requestFacts: [
|
|
{
|
|
id: "server-observed-ip",
|
|
category: "request",
|
|
label: "服务端连接地址",
|
|
value: "127.0.0.1",
|
|
inference: "后端从这次请求的 TCP 连接中看到的来源地址。",
|
|
sensitivity: "high",
|
|
},
|
|
],
|
|
permissionFacts: [
|
|
{
|
|
id: "geolocation",
|
|
category: "permission",
|
|
label: "定位授权",
|
|
value: "未授权",
|
|
inference: "用户尚未授予定位权限",
|
|
sensitivity: "critical",
|
|
},
|
|
],
|
|
networkDiagnostics: {
|
|
server: { observedIp: "127.0.0.1" },
|
|
webrtc: { summary: { total: 2, public: 0, private: 0, mdns: 2 } },
|
|
},
|
|
},
|
|
getMessages("en"),
|
|
);
|
|
|
|
assert.match(report, /Browser exposure profile report/);
|
|
assert.match(report, /Stage one: local profile/);
|
|
assert.match(report, /Stage two: backend request/);
|
|
assert.match(report, /Stage three: permission evidence/);
|
|
assert.match(report, /Server address seen: 127\.0\.0\.1/);
|
|
assert.match(report, /\[Medium\] System timezone: Asia\/Shanghai/);
|
|
assert.doesNotMatch(report, /浏览器暴露画像报告|第一阶段|服务端看到的地址/);
|
|
});
|
|
});
|