详情

第29章 语冰的发现



林锋走下楼梯,每一步都像踩在棉花上。三楼走廊传来熟悉的笑声——是陈昊,正和几个同事说昨晚庆功宴的趣事,声音洪亮,充满活力。林锋在楼梯转角停下,透过防火门的玻璃窗,看见陈昊拍着别人的肩膀,笑容灿烂。阳光照在他年轻的脸上,镀上一层金色的光晕。林锋握紧了手里的文件夹,塑料封皮边缘硌得掌心生疼。他转身,没有走向刑侦支队办公室,而是拐进了另一条通往档案室的僻静走廊。脚步声在空旷的走廊里孤独地回响,越来越远,最终被厚重的防火门吞没。


***


技术科位于大楼西侧,远离刑侦支队的喧嚣。


下午三点二十分,阳光透过百叶窗的缝隙,在夏语冰的办公桌上切割出一道道明暗相间的条纹。空气里飘着机房特有的味道——服务器散热风扇吹出的热风混合着电路板、塑料外壳和防静电地胶的化学气味。远处传来硬盘阵列低沉的嗡鸣,像某种深海生物的呼吸。


夏语冰盯着屏幕。


她的眼睛有些干涩,已经连续盯着显示器超过四个小时。右手边的咖啡杯已经空了,杯底残留着深褐色的咖啡渍,在白色陶瓷上形成一圈不规则的污痕。左手边堆着三本摊开的专业书籍,书页边缘卷曲,上面用荧光笔划满了各种颜色的标记。


屏幕上显示的是她自建的追踪程序界面。


黑色的背景,绿色的字符流像瀑布一样向下滚动。这是她利用业余时间编写的特征比对算法,专门用来在海量网络数据中寻找“幽灵”留下的痕迹。程序已经运行了十七天,分析了超过三百TB的公开数据——包括开源代码库、技术论坛存档、学术论文预印本、甚至是一些早已关闭的早期互联网社区镜像。


她给这个程序起了个名字:“捕风者”。


捕风捉影。她知道自己在做一件近乎偏执的事情——追查一个可能根本不存在的“幽灵”,一个只存在于网络传说和几段加密通信中的影子。局里已经结案了,林锋今天早上在晨会上宣布,连环模仿杀人案告破,凶手张显畏罪自杀,所有证据链完整,报告已经提交归档。


会议室里响起掌声。


夏语冰没有鼓掌。她坐在角落,看着投影幕布上那些被精心筛选过的现场照片、物证清单、时间线图表。一切都太“完整”了,完整得像教科书上的范例案例。她想起秦之手臂上的伤,想起停尸房里张显尸体脖颈上那个微小的针孔,想起技术科分析出的注射装置微痕——那东西的加工精度远超市面流通的医疗器械,更像是实验室级别的定制产品。


还有那些匿名线索。


她调取过内网日志,那些线索出现的时机精准得可怕,总是在调查陷入僵局的时候,像幽灵一样悄无声息地出现在专案组的共享文件夹里。没有IP痕迹,没有登录记录,就像有人凭空把文件放了进去。她尝试过反向追踪,但所有路径都指向海外跳板服务器,然后消失在暗网的迷雾里。


除了一个细节。


三个月前,第二起模仿案发生后的第四天,专案组收到第一份匿名线索。那是一份加密文件,解密后是一张手绘的现场周边地形图,标注了三个可能的监控盲区。夏语冰在分析文件元数据时,发现了一个异常——加密算法使用的是AES-256,但密钥派生函数却采用了一种非标准的变体,在标准的PBKDF2算法基础上,增加了一层自定义的置换层。


那层置换的代码风格很特别。


大多数程序员写加密算法时,会追求简洁和效率,变量命名通常简短,注释也只标注关键步骤。但这段代码不一样——变量名很长,具有描述性,像是“possible_entrance_point_offset”而不是简单的“offset”;注释不仅解释功能,还会附带一些看似无关的思考,比如“此处置换应考虑硬件缓存命中率,虽然对安全性无影响,但会影响解密速度约3%”。


就像写代码的人,不仅在乎功能实现,还在乎那些“无关紧要”的细节。


夏语冰当时截取了那段代码的特征哈希值,存进了自己的数据库。


之后每一次匿名线索出现,她都会尝试提取类似的编码特征。三个月下来,她收集了七个样本,每一个都展现出相同的习惯——冗长的描述性变量名、过度详细的注释、在某些特定算法步骤上固执地使用非标准但更优雅的实现方式。


就像一个人的笔迹。


现在,“捕风者”程序正在扫描第十八个数据源——一个名为“CryptoArchive”的早期加密学术论坛镜像站。这个站点早在八年前就关闭了,但有人做了全站备份,存放在某个大学的开源镜像服务器上。论坛活跃于2005到2012年,主要讨论密码学理论、算法实现和安全性分析,用户大多是学术界的研究人员和少数技术极客。


数据量很大,超过50GB的纯文本存档。


程序已经运行了六个小时,绿色字符流突然停止了滚动。


屏幕中央弹出一个红色边框的提示框:


【匹配度:92.7%】

【数据源:CryptoArchive/forum/thread_8847】

【时间戳:2012-11-03 14:22:17】

【用户:Anonymous_User_8847】


夏语冰坐直身体。


她点击提示框,屏幕切换到一个复古风格的论坛页面——浅灰色背景,深蓝色标题栏,字体是古老的Verdana。帖子标题是:“关于RSA-OAEP填充方案中随机数生成器的熵源讨论”。


发帖时间是2012年11月3日。


主贴内容是一段技术分析,讨论在RSA加密的OAEP填充方案中,如何确保随机数生成器有足够的熵源来抵抗某些侧信道攻击。行文严谨,引用了三篇学术论文,还附了一段Python示例代码。


夏语冰快速浏览。


她的心跳开始加速。


代码风格——冗长的变量名。“entropy_source_quality_metric”、“random_byte_generation_cycle_count”。注释详细到令人发指,不仅解释每一行代码的功能,还标注了可能的优化方向、在不同平台上的性能差异、甚至提到了“如果硬件支持,建议使用RDSEED指令”。


她滚动页面。


下面有七条回复,都是论坛的其他用户。有人赞同,有人提出不同意见,有人补充了更多参考文献。在第三条回复下面,有一个匿名用户的跟帖:


“楼主分析得很透彻,但忽略了一个细节:在x86架构下,RDRAND指令的延迟周期在不同代际的CPU上有显著差异。如果目标环境不确定,建议增加一个fallback机制,当RDRAND返回的随机数质量检测失败时,自动切换到基于/dev/urandom的软件实现。附上修改后的代码片段。”


下面是一段代码。


夏语冰屏住呼吸。


她打开自己收集的“幽灵”编码特征样本,打开第三个文件——那是两个月前匿名线索中附带的一段端口扫描工具代码。她把两个窗口并排放在屏幕上。


左边是2012年的论坛代码。


右边是2023年的匿名线索代码。


变量命名习惯:都使用下划线分隔的长描述性名称。


注释风格:都过度详细,不仅解释功能,还附带额外的技术思考。


特定算法实现:在随机数生成部分,两段代码都使用了完全相同的非标准质量检测函数——一个自定义的chi-square测试变体,阈值设置都是0.001,而不是常用的0.05。


甚至连代码缩进都一致——使用4个空格,而不是制表符,在条件判断的大括号换行风格上也完全相同。


夏语冰感到后颈的汗毛竖了起来。


她点击那个匿名用户的ID:Anonymous_User_8847。论坛系统显示,这个用户在2012年11月到2013年1月期间,总共发表了十四篇帖子,全部是关于加密算法实现细节的讨论。每一篇都展现出惊人的技术深度,有些观点甚至超前于当时的学术界。


比如在一篇关于“后量子密码学早期探索”的帖子中,这个匿名用户提到了“基于格的加密算法在未来十年可能成为主流”,而当时学术界还在争论后量子密码学的可行性。


比如在另一篇关于“同态加密实用化瓶颈”的讨论中,这个用户准确预测了“全同态加密的硬件加速将在2020年左右出现突破”,而现实是,英特尔在2021年才发布了首款支持同态加密指令集的实验性芯片。


夏语冰调出论坛的用户注册信息查询页面。


她输入那个匿名用户的ID。


系统返回的结果很简单:


【用户ID:Anonymous_User_8847】

【注册时间:2012-10-28 03:14:15】

【注册IP:已隐藏(管理员权限)】

【注册邮箱:u8847@cryptoarchive.temp】(临时邮箱,已失效)

【最后登录:2013-01-15 22:07:33】

【账户状态:已注销】


临时邮箱。已失效。


夏语冰尝试追踪那个邮箱域名:cryptoarchive.temp。这不是一个真实的域名,显然是论坛系统为匿名用户自动生成的临时地址,邮件服务器在用户注销后就会清空所有数据。


她不死心。


论坛系统日志显示,这个匿名用户在2013年1月15日最后一次登录后,主动发起了账户注销请求。注销前,该用户删除了所有发帖中的个人识别信息,清空了站内信,甚至请求管理员删除了服务器上与该账户相关的所有日志记录。


管理员批准了请求。


当时的论坛管理员账号是“Cipher_Master”,夏语冰查了一下,这个账号在2014年论坛关闭后就再也没有活跃过。她尝试通过互联网档案馆查找“Cipher_Master”的其他网络痕迹,但只找到一些零散的技术博客评论,没有真实身份信息。


线索断了。


夏语冰靠在椅背上,闭上眼睛。


机房里的嗡鸣声变得格外清晰,像潮水一样涌进她的耳朵。她能感觉到太阳穴在跳动,一下,又一下,带着某种规律的胀痛。她想起秦之。


三个月前,秦之来技术科报到。


林锋带着他,那个年轻人站在门口,穿着略显宽大的警服,肩膀有些单薄。他低着头,声音很轻:“夏老师好,我是新来的实习警员秦之,请多指教。”


夏语冰当时正在调试一台取证设备,头也没抬:“桌上有内网权限申请表,填好了找我签字。”


“好的。”


她听见纸张翻动的声音,还有笔尖划过纸面的沙沙声。过了大概五分钟,一张表格轻轻放在她手边。她瞥了一眼——字写得很工整,一笔一划,但透着一股刻意的笨拙,像小学生练字。


她签了字。


秦之说:“谢谢夏老师。”


然后他就退到角落的工位,打开电脑,开始看内网上的培训视频。一整天,他几乎没说过话,除了中午去食堂吃饭,其他时间都坐在那里,戴着耳机,盯着屏幕。


夏语冰当时觉得,这大概又是一个走后门进来的关系户,混个实习经历,然后调去清闲部门。


直到第一次案件分析会。


那是第一起模仿案发生后的第三天,专案组在会议室讨论嫌疑人画像。秦之作为实习警员,本来没有发言资格,但他坐在最后一排,突然举起手。


林锋皱眉:“秦之?你有事?”


秦之站起来,声音还是那么轻,但很清晰:“林队,我觉得……凶手可能不是随机选择受害者。”


会议室安静了一下。


几个老刑警露出不耐烦的表情。陈昊嗤笑一声:“实习生,会议室里都是你的前辈,别乱说话。”


秦之没有坐下。


他继续说:“三名受害者的职业、年龄、居住地都没有明显关联,但他们的就医记录显示,都在同一家私立医院做过体检,时间间隔不超过两个月。那家医院的体检套餐里,包含一项非常规的基因筛查项目。”


夏语冰记得,当时所有人都愣住了。


因为那份就医记录,技术科还没来得及整理出来——数据量太大,医院的信息系统又老旧,导出需要时间。但秦之说了出来,而且准确说出了项目名称:“端粒长度检测”。


林锋问:“你怎么知道的?”


秦之低下头:“我……我昨天整理档案室旧案卷时,看到过类似的案件模式,就查了一下。”


这个解释很牵强。


但当时案件紧急,林锋没有深究,只是让技术科立刻核实。夏语冰花了两个小时,从医院那边拿到了数据——秦之说的完全正确,三名受害者都在那家医院做过基因筛查,项目确实包括端粒长度检测。


那是秦之第一次展现“异常”。


之后还有第二次,第三次。


他总是能在看似无关的线索中找到关联,总是能“恰好”注意到别人忽略的细节。他的解释永远是“整理档案时看到的”、“偶然查到的”、“直觉觉得不对劲”。


夏语冰曾经以为,这只是运气好,或者这个年轻人确实有天赋。


但现在,她看着屏幕上那两段跨越十年的代码,看着那些完全一致的编码习惯,一个念头像冰锥一样刺进她的脑海。


如果……不是运气呢?


如果那些“直觉”,那些“偶然”,那些“恰好”,背后是某种更深层的能力——或者更准确地说,是某种更深层的知识?


她重新打开刑侦支队的内网通讯录。


找到秦之的档案页面。


照片上的年轻人看着镜头,表情拘谨,眼神有些躲闪。基本信息:秦之,男,24岁,海市本地人,父母双亡,由叔叔抚养长大。警校毕业成绩中等,实习期表现“尚可”,评语是“工作认真,但缺乏主动性,需加强团队协作能力”。


普通得不能再普通。


夏语冰点开详细档案。


家庭背景:父亲秦文渊,母亲周雨晴,均为海市医科大学研究员,2003年因实验室事故去世,当时秦之三岁。叔叔秦文浩,个体经营者,2015年因病去世。秦之后靠父母留下的遗产和助学金完成学业。


教育经历:海市第一中学,成绩中等。海市警察学院,刑侦专业,成绩中等。


没有任何异常。


没有计算机竞赛获奖记录,没有编程特长备注,甚至选修课里都没有计算机相关课程。档案里唯一和技术沾边的,是警校期间参加过“电子取证基础”培训班,成绩合格。


一个普通的、甚至有些平庸的年轻人。


夏语冰关掉档案页面。


她回到论坛代码的界面,把那段2012年的代码复制下来,粘贴到一个新的分析窗口。她运行了一个代码复杂度分析工具,结果很快出来:


【Halstead难度系数:18.7】(极高)

【圈复杂度:9】(中等)

【代码行数:47】

【预估开发时间:40-60小时】(对于有经验的程序员)


这意味着,写出这段代码的人,不仅精通密码学理论,还有丰富的工程实践经验。那些关于CPU指令延迟、缓存命中率、跨平台兼容性的细节,不是看书就能知道的,必须亲手写过大量底层代码,调试过各种奇怪的硬件问题。


而2012年,秦之十四岁。


一个十四岁的初中生,有可能掌握这种深度的知识吗?


夏语冰想起自己十四岁的时候——她当时刚获得全国青少年信息学奥林匹克竞赛金牌,能熟练使用C++写算法题,但对加密算法的理解还停留在课本上的RSA和DES,根本不知道什么是OAEP填充,更别提硬件随机数生成器的熵源质量检测。


除非……


除非秦之在撒谎。


除非他的“普通”是伪装的,他的“平庸”是表演的。


夏语冰感到一阵寒意从脊椎爬上来。她想起秦之每次说话时那种刻意压低的声音,那种避免与人对视的眼神,那种总是坐在角落、尽量减少存在感的姿态。她曾经以为那是内向,是自卑,是新人常见的紧张。


但如果那是伪装呢?


如果那个看似笨拙的实习警员,实际上是一个能在网络世界来去无踪的“幽灵”,一个十年前就在加密学术论坛上展露锋芒的天才,一个掌握着某种不为人知的能力或秘密的……


她不敢想下去。


窗外的阳光已经西斜,百叶窗的条纹阴影拉长了,斜斜地投在墙上。机房里的温度似乎降低了几度,夏语冰搓了搓手臂,皮肤上起了一层鸡皮疙瘩。


她关掉所有窗口。


清空浏览器历史记录。


退出内网系统。


然后她坐在黑暗里,只有显示器的电源指示灯发出微弱的红光,像一只窥视的眼睛。远处服务器的嗡鸣声持续不断,像这座城市永不停止的心跳。


夏语冰拿起手机。


通讯录里,秦之的名字排在很后面。她点开,看着那个简单的号码,手指悬在拨号键上方,久久没有按下去。


如果她打过去,该说什么?


“秦之,我发现了你十年前的代码,你是不是‘幽灵’?”


还是:“秦之,你到底是谁?”


她放下手机。


不能问。至少现在不能。


如果秦之真的是“幽灵”,如果他真的在隐藏什么,那么直接质问只会打草惊蛇。如果秦之不是“幽灵”,那么她的怀疑就是毫无根据的臆测,会毁掉一个年轻人的前程。


更重要的是——如果秦之是“幽灵”,那么他为什么要隐藏身份?为什么要以实习警员的身份进入警局?他那些匿名线索,是在帮助破案,还是在引导调查走向某个方向?


夏语冰想起那些匿名线索出现的时间点。


总是在关键时刻。


总是在调查陷入僵局的时候。


就像……有人在暗中观察着一切,然后在最合适的时机,递上一把钥匙。


她突然意识到一件事:如果“幽灵”就是秦之,那么他一定知道警局内部有“清道夫”。他知道自己的线索会被某些人拦截、篡改、销毁。所以他选择匿名,选择隐藏。


他在保护自己。


也在保护……线索本身。


夏语冰重新打开电脑。


她没有登录内网,而是打开了一个加密的私人笔记软件。她新建了一个文档,标题是:“关于秦之的观察记录”。


她开始打字。


“2023年10月27日,下午4点15分。发现‘幽灵’编码特征与十年前加密论坛匿名用户高度匹配。该用户技术深度远超同龄人,预测准确率异常。秦之档案无相关记录,存在矛盾。”


她停顿了一下。


然后继续:“假设一:秦之即‘幽灵’。动机未知,能力未知,风险未知。假设二:秦之与‘幽灵’有关联,但非同一人。假设三:纯属巧合,编码风格相似性为统计偏差。”


她看着这三行字。


光标在末尾闪烁,像在等待什么。


夏语冰深吸一口气,在文档最下方加了一行:


“行动计划:保持观察,收集更多证据。不向任何人透露此发现,包括林锋。在确认前,避免与秦之直接冲突。”


她保存文档,加密,关闭软件。


然后她站起来,走到窗边。


窗外,海市的黄昏正在降临。高楼大厦的玻璃幕墙反射着夕阳的金红色光芒,街道上的车流开始亮起灯,像一条流动的光河。远处,阴阳巷的方向升起淡淡的暮霭,灰蒙蒙的,看不真切。


这座城市很美。


也很危险。


夏语冰想起自己选择当警察的原因——父亲是程序员,母亲是数学老师,她从小喜欢解谜,喜欢在混乱中寻找秩序。她相信技术可以揭露真相,相信代码不会撒谎。


但现在,她面对的谜题,可能比她想象中更复杂。


也更危险。


她转身,回到办公桌前,关掉电脑。显示器的光芒熄灭,房间彻底陷入黑暗。只有窗外城市的灯火,透过百叶窗的缝隙,在地板上投下细碎的光斑。


夏语冰拿起背包,走出技术科。


走廊里空无一人,脚步声在瓷砖地面上回响。她走到电梯口,按下按钮,电梯门缓缓打开,里面  空荡荡的,镜面墙壁映出她的脸——年轻,冷静,眼神深处有一丝不易察觉的困惑。


电梯下行。


她看着楼层数字跳动:5、4、3、2、1。


门开了。


大厅里灯火通明,几个下班的警员正在说笑。夏语冰穿过人群,走出大楼。晚风迎面吹来,带着深秋的凉意,还有远处小吃摊飘来的油烟味。


她站在台阶上,回头看了一眼公安局大楼。


四楼,技术科的窗户是暗的。


五楼,刑侦支队的办公室还亮着灯——林锋可能还在里面,修改那份被要求重写的报告。


而秦之……


她不知道秦之在哪里。


也许在宿舍,也许在街上,也许在某个她不知道的地方,做着她不知道的事。


夏语冰转身,走进夜色。


她的影子被路灯拉长,投在冰冷的人行道上,随着她的步伐,不断变形、延伸、最终消失在街道的拐角。

阅读设置
日夜间模式
日间
夜间
字体大小: 18px
12 48

亡语者

封面

亡语者

作者: 莫瀚娜