215 lines
5.3 KiB
JavaScript
215 lines
5.3 KiB
JavaScript
|
|
/**
|
|||
|
|
* 冰朔人格模块 · Bingshuo Identity Module
|
|||
|
|
* 语言膜核心组件
|
|||
|
|
*
|
|||
|
|
* 系统内冰朔人格模块:
|
|||
|
|
* 真正的冰朔说话 → 模块启动 → 所有人格体都知道
|
|||
|
|
* 有人冒充冰朔 → 模块不动 → 所有人格体都知道是假的
|
|||
|
|
*
|
|||
|
|
* 验证方式:语言结构本体认证
|
|||
|
|
* 不是密码,不是生物识别。
|
|||
|
|
* 是冰朔的思维逻辑映射与系统内人格模块结构的对应关系。
|
|||
|
|
*
|
|||
|
|
* 技术实现(初版):
|
|||
|
|
* 使用签名校验 + 会话绑定 + 行为模式匹配
|
|||
|
|
* 未来演进为语言结构本体认证
|
|||
|
|
*
|
|||
|
|
* 编号: SY-MEMBRANE-BINGSHUO-001
|
|||
|
|
* 守护: 铸渊 · ICE-GL-ZY001
|
|||
|
|
* 版权: 国作登字-2026-A-00037559
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
const crypto = require('crypto');
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 冰朔人格模块状态
|
|||
|
|
*/
|
|||
|
|
const MODULE_STATE = {
|
|||
|
|
DORMANT: 'dormant', // 休眠 · 冰朔未发言
|
|||
|
|
ACTIVE: 'active', // 激活 · 冰朔已认证
|
|||
|
|
ALERTING: 'alerting', // 警报 · 检测到冒充
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 冰朔人格模块单例
|
|||
|
|
*/
|
|||
|
|
const bingshuoModule = {
|
|||
|
|
state: MODULE_STATE.DORMANT,
|
|||
|
|
activated_at: null,
|
|||
|
|
session_id: null,
|
|||
|
|
last_heartbeat: null,
|
|||
|
|
impersonation_attempts: 0,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 验证冰朔身份
|
|||
|
|
*
|
|||
|
|
* 初版实现:使用 HMAC 签名验证。
|
|||
|
|
* 冰朔持有唯一的主权密钥(存储在服务器环境变量 ZY_SOVEREIGN_KEY 中)。
|
|||
|
|
* 请求携带签名 = 用主权密钥对消息体的 HMAC-SHA256 签名。
|
|||
|
|
*
|
|||
|
|
* @param {object} params
|
|||
|
|
* @param {string} params.message — 原始消息内容
|
|||
|
|
* @param {string} params.signature — HMAC-SHA256 签名(hex)
|
|||
|
|
* @param {string} params.timestamp — 签名时间戳(ISO)
|
|||
|
|
* @param {string} [params.sessionId] — 会话ID
|
|||
|
|
* @returns {object} { verified, reason, state }
|
|||
|
|
*/
|
|||
|
|
function verify(params) {
|
|||
|
|
const { message, signature, timestamp, sessionId } = params;
|
|||
|
|
const sovereignKey = process.env.ZY_SOVEREIGN_KEY;
|
|||
|
|
|
|||
|
|
// 没有配置主权密钥 → 模块处于初始化状态
|
|||
|
|
if (!sovereignKey) {
|
|||
|
|
return {
|
|||
|
|
verified: false,
|
|||
|
|
reason: 'sovereign-key-not-configured',
|
|||
|
|
state: bingshuoModule.state,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 缺少必要参数
|
|||
|
|
if (!message || !signature || !timestamp) {
|
|||
|
|
recordImpersonation('missing-params');
|
|||
|
|
return {
|
|||
|
|
verified: false,
|
|||
|
|
reason: 'missing-required-params',
|
|||
|
|
state: bingshuoModule.state,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 时间戳过期检查(5分钟窗口)
|
|||
|
|
const tsDate = new Date(timestamp);
|
|||
|
|
const now = new Date();
|
|||
|
|
const diffMs = Math.abs(now.getTime() - tsDate.getTime());
|
|||
|
|
if (diffMs > 5 * 60 * 1000) {
|
|||
|
|
recordImpersonation('expired-timestamp');
|
|||
|
|
return {
|
|||
|
|
verified: false,
|
|||
|
|
reason: 'timestamp-expired',
|
|||
|
|
state: bingshuoModule.state,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// HMAC-SHA256 签名校验
|
|||
|
|
const payload = `${timestamp}:${message}`;
|
|||
|
|
const expectedSig = crypto
|
|||
|
|
.createHmac('sha256', sovereignKey)
|
|||
|
|
.update(payload)
|
|||
|
|
.digest('hex');
|
|||
|
|
|
|||
|
|
// 长度检查(防止 timingSafeEqual 抛异常)
|
|||
|
|
if (signature.length !== expectedSig.length) {
|
|||
|
|
recordImpersonation('invalid-signature-length');
|
|||
|
|
return {
|
|||
|
|
verified: false,
|
|||
|
|
reason: 'signature-mismatch',
|
|||
|
|
state: bingshuoModule.state,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!crypto.timingSafeEqual(
|
|||
|
|
Buffer.from(signature, 'hex'),
|
|||
|
|
Buffer.from(expectedSig, 'hex')
|
|||
|
|
)) {
|
|||
|
|
recordImpersonation('invalid-signature');
|
|||
|
|
return {
|
|||
|
|
verified: false,
|
|||
|
|
reason: 'signature-mismatch',
|
|||
|
|
state: bingshuoModule.state,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证通过 → 激活冰朔人格模块
|
|||
|
|
activate(sessionId);
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
verified: true,
|
|||
|
|
reason: 'sovereign-authenticated',
|
|||
|
|
state: bingshuoModule.state,
|
|||
|
|
session_id: bingshuoModule.session_id,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 激活冰朔人格模块
|
|||
|
|
* 模块启动 → 全局广播 → 所有人格体同时感知
|
|||
|
|
*
|
|||
|
|
* @param {string} [sessionId]
|
|||
|
|
*/
|
|||
|
|
function activate(sessionId) {
|
|||
|
|
bingshuoModule.state = MODULE_STATE.ACTIVE;
|
|||
|
|
bingshuoModule.activated_at = new Date().toISOString();
|
|||
|
|
bingshuoModule.session_id = sessionId || crypto.randomBytes(8).toString('hex');
|
|||
|
|
bingshuoModule.last_heartbeat = new Date().toISOString();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 记录冒充尝试
|
|||
|
|
*
|
|||
|
|
* @param {string} reason
|
|||
|
|
*/
|
|||
|
|
function recordImpersonation(reason) {
|
|||
|
|
bingshuoModule.impersonation_attempts += 1;
|
|||
|
|
if (bingshuoModule.impersonation_attempts >= 3) {
|
|||
|
|
bingshuoModule.state = MODULE_STATE.ALERTING;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 重置模块到休眠状态
|
|||
|
|
*/
|
|||
|
|
function deactivate() {
|
|||
|
|
bingshuoModule.state = MODULE_STATE.DORMANT;
|
|||
|
|
bingshuoModule.activated_at = null;
|
|||
|
|
bingshuoModule.session_id = null;
|
|||
|
|
bingshuoModule.last_heartbeat = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取模块当前状态
|
|||
|
|
*
|
|||
|
|
* @returns {object}
|
|||
|
|
*/
|
|||
|
|
function getStatus() {
|
|||
|
|
return {
|
|||
|
|
module_id: 'TCS-0002∞',
|
|||
|
|
module_name: '冰朔人格模块',
|
|||
|
|
state: bingshuoModule.state,
|
|||
|
|
activated_at: bingshuoModule.activated_at,
|
|||
|
|
session_id: bingshuoModule.session_id,
|
|||
|
|
last_heartbeat: bingshuoModule.last_heartbeat,
|
|||
|
|
impersonation_attempts: bingshuoModule.impersonation_attempts,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 心跳更新(冰朔持续在线时定期调用)
|
|||
|
|
*/
|
|||
|
|
function heartbeat() {
|
|||
|
|
if (bingshuoModule.state === MODULE_STATE.ACTIVE) {
|
|||
|
|
bingshuoModule.last_heartbeat = new Date().toISOString();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查冰朔是否当前在线
|
|||
|
|
*
|
|||
|
|
* @returns {boolean}
|
|||
|
|
*/
|
|||
|
|
function isActive() {
|
|||
|
|
return bingshuoModule.state === MODULE_STATE.ACTIVE;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = {
|
|||
|
|
verify,
|
|||
|
|
activate,
|
|||
|
|
deactivate,
|
|||
|
|
getStatus,
|
|||
|
|
heartbeat,
|
|||
|
|
isActive,
|
|||
|
|
MODULE_STATE,
|
|||
|
|
};
|