☰
Delphi XE10.2 加密实战:TMS Cryptography Pack 3.4.0.1 拆包与 AES/RSA 落地
2026/10/18 13:56:59 网站建设 项目流程

简介:TMS Cryptography Pack 3.4.0.1 是面向 Delphi XE10.2 开发者的加密组件库,适合需要在桌面与移动应用中集成数据保护、安全通信的中高级开发者。它覆盖 AES、DES、3DES、Blowfish、Twofish、RC4、RSA 等对称与非对称算法,并提供 MD5、SHA 系列哈希、HMAC 消息认证码、数字签名与 X.509 证书管理,同时支持 PKCS#7 标准与加密级随机数生成,可满足文件加密、密钥交换、S/MIME 邮件等场景。资源包共 210 个文件,以 dcu 编译单元、o 目标文件、bmp 位图、dcp 包缓存、a 静态库、res 资源、bpl 运行时包及 dpk、dproj 工程文件为主,另含 dylib、pdf 文档与示例 exe,整体约 71.54MB,目录结构便于按模块查阅。目前已有 270 人学习下载,可帮助读者快速理解各加密组件的 API 设计与跨平台调用方式,为构建符合现代安全标准的 Delphi 应用提供完整参考。

1. 拆开一个 Delphi 加密包:TMS Cryptography Pack 3.4.0.1 到底能干什么

如果你正在维护一套 Delphi XE10.2 的老项目,突然接到需求要在客户端做 AES 加密、RSA 签名或者哈希校验,第一反应大概率是去翻 System.Hash、System.NetEncoding 这些自带单元。能用,但一旦涉及证书解析、PKCS#7 封装、椭圆曲线或者国密算法,自带库就开始捉襟见肘。这时候 TMS Cryptography Pack 这类第三方加密组件包就成了绕不开的选项。我手上这份是 3.4.0.1 版本、面向 XE10.2 的发布包,压缩包名里带着下载站后缀,说明它是从公开渠道流出的完整安装包,不是阉割版。它解决的核心问题很明确:把散落在 OpenSSL、Windows CryptoAPI、.NET 之间的加密能力,收敛成一套原生 Delphi 接口,让 XE10.2 这种较老但仍在生产环境跑的 IDE 能直接调用。适合谁?适合那些不想为了一个签名功能去折腾 DLL 绑定、又必须保证编译期类型安全的 Delphi 工程师。下面我按实际拆包和接入的顺序,把这份资源从结构到落地讲透。

2. 包结构与 XE10.2 安装路径:先看清目录再动手

2.1 解压后你会看到什么

拿到 rar 之后别急着双击安装程序。我一般先解压到一个短路径目录,比如D:\Libs\TMSCrypto3401,因为 Delphi 的搜索路径对空格和中文相当敏感,路径里带空格后期编译报「unit not found」能查到你怀疑人生。解压后典型结构是这样的:

目录/文件作用是否必须
source/全部 .pas 源码,含核心加密单元是
packages/XE10.2 对应的 .dpk 包工程是
demos/各算法示例工程建议保留
lib/预编译 .dcu(按版本分目录)可选
readme/license版本与授权说明参考

关键点在于packages/下会有按 IDE 版本命名的子目录,XE10.2 对应的是DXE102这类标识。如果你看到的是DXE103、DXE104,那说明这份包不是给 XE10.2 用的,强行装会在编译期报接口不匹配。

2.2 安装到 IDE 的两种方式

第一种是走 .dpk 包工程。用 XE10.2 打开packages/DXE102下的包工程,右键 Install,IDE 会把设计期包注册进去。第二种是纯源码引用,不装包,直接把source/加到项目的搜索路径里。两种方式的差别很实际:装包适合要在窗体设计器里拖控件、用可视化组件的场景;纯源码适合服务端或控制台程序,避免设计期包带来的 IDE 启动负担。

我一般对老项目用第二种,因为 XE10.2 装太多设计期包之后,IDE 启动能慢到让人想砸键盘。纯源码引用的配置如下:

# 在项目 .dproj 的 DCC_UnitSearchPath 里追加,注意用分号分隔 D:\Libs\TMSCrypto3401\source;D:\Libs\TMSCrypto3401\source\core

改完之后重新打开项目,让 IDE 重新解析搜索路径。如果之前编译过,先 Build 而不是 Compile,否则旧的 .dcu 缓存会继续生效,你会以为新路径没起作用。

2.3 验证安装是否成功

写一个最小单元测试,只引用核心单元,编译通过就说明路径没问题:

program CheckInstall; {$APPTYPE CONSOLE} uses System.SysUtils, TMS.CryptoCore; // 核心单元,具体名称以 source 下实际文件为准 begin try WriteLn('TMS Crypto unit loaded, version check passed.'); except on E: Exception do WriteLn('Load failed: ' + E.Message); end; ReadLn; end.

这段代码不调用任何算法,只验证单元能否被编译器找到并链接。逻辑说明:uses里引用的单元名必须和source/下实际文件名一致,不同小版本可能改过命名,别照抄网上的旧例子。参数说明:无。如果这一步就报 unit not found,回去检查搜索路径有没有写错盘符或漏掉子目录。

提示:XE10.2 的编译器对大小写不敏感,但搜索路径里的目录名必须真实存在,写错一个字母就会静默跳过该路径,不会给你明确报错。

3. 核心加密能力的调用方式:AES、RSA 与哈希怎么落地

3.1 对称加密 AES 的典型调用链

TMS 这套包的对称加密接口设计得比较直白,基本是「建上下文 → 设密钥和模式 → 喂数据 → 取结果」四步。以 AES-256-CBC 为例,常见写法是:

uses System.SysUtils, System.Classes, TMS.Crypto.AES; // 以实际单元名为准 function EncryptAES(const PlainText, KeyHex, IVHex: string): string; var AES: TTMSAES; Key, IV, Input, Output: TBytes; begin // 十六进制字符串转字节数组,密钥必须是 32 字节对应 AES-256 Key := HexToBytes(KeyHex); IV := HexToBytes(IVHex); Input := TEncoding.UTF8.GetBytes(PlainText); AES := TTMSAES.Create; try AES.Mode := amCBC; // 分组模式,CBC 需要 IV AES.KeySize := ks256; // 密钥长度,必须和 Key 字节数匹配 AES.SetKey(Key); AES.SetIV(IV); Output := AES.Encrypt(Input); Result := BytesToHex(Output); finally AES.Free; end; end;

逻辑说明:先做编码转换,把明文统一成 UTF-8 字节,避免中文在不同代码页下加密结果不一致。参数说明:KeySize必须和Key的实际字节数对应,设成 ks256 却只给 16 字节密钥,多数实现会直接抛异常而不是自动补齐。Mode选 CBC 时 IV 必须提供且每次加密都应更换,选 ECB 则不需要 IV 但安全性差,只适合做兼容老系统的场景。

3.2 非对称加密 RSA 的密钥与填充

RSA 部分最容易翻车的是填充模式。TMS 包通常支持 PKCS#1 v1.5 和 OAEP 两种,前者兼容性好但被认为不够安全,后者是新系统首选。调用时密钥来源有两种:直接加载 PEM 文件,或者从字节数组导入。我一般用文件加载,便于密钥轮换:

uses TMS.Crypto.RSA; function SignData(const Data: TBytes; const PrivateKeyFile: string): TBytes; var RSA: TTMSRSA; begin RSA := TTMSRSA.Create; try RSA.LoadPrivateKeyFromFile(PrivateKeyFile); // 支持 PEM/DER,看实现 RSA.Padding := rpPKCS1; // 或 rpOAEP RSA.HashAlg := haSHA256; // 签名摘要算法 Result := RSA.Sign(Data); finally RSA.Free; end; end;

逻辑说明:签名和验签必须使用同一套填充与摘要算法,否则验签端一定失败。参数说明:HashAlg选 SHA256 是当前主流,SHA1 只用于对接遗留系统。Padding如果对端是 Java 或 .NET 默认实现,先确认它们用的是 PKCS#1 还是 OAEP,这个不统一是跨语言对接最常见的坑。

3.3 哈希与 HMAC 的边界

哈希本身没有密钥,HMAC 是带密钥的哈希,两者用途不同。做完整性校验用哈希,做消息认证用 HMAC。TMS 包一般把这两类放在同一单元里,调用时注意输出编码:

uses TMS.Crypto.Hash; function SHA256Hex(const Data: TBytes): string; var H: TTMSHash; begin H := TTMSHash.Create(haSHA256); try H.Update(Data); Result := H.FinalHex; // 直接取十六进制,省去手动转换 finally H.Free; end; end;

逻辑说明:Update可以多次调用做流式哈希,适合大文件分块读取。参数说明:FinalHex和Final的区别在于前者返回字符串、后者返回字节数组,按下游接口选。注意哈希结果不可逆,别指望从摘要还原原文。

4. 避坑与排查:老 IDE 接加密包的五个血泪经验

4.1 编译报「不兼容的单元版本」

现象:装完包后编译项目,报 unit was compiled with a different version of System。原因:lib/下的预编译 .dcu 是用别的 IDE 版本编的,XE10.2 的编译器不认。解决:删掉lib/目录,强制从source/重新编译,或者只保留 DXE102 对应的 dcu 子目录。

4.2 加密结果和 Java 端对不上

现象:同样的明文和密钥,Delphi 加密出来的密文 Java 解不开。原因:九成是编码或填充不一致,比如 Delphi 端用了 UTF-8 而 Java 端用了 GBK,或者 IV 处理方式不同。解决:先把明文统一成 UTF-8 字节,再逐字节比对密钥和 IV 的十六进制值,最后确认填充模式。别靠猜,打印中间值。

4.3 运行时抛「密钥长度无效」

现象:调用 AES 时异常提示 invalid key size。原因:KeySize设成 256 但传入的密钥只有 16 字节。解决:AES-128 对应 16 字节、AES-192 对应 24 字节、AES-256 对应 32 字节,三者不能混。检查密钥生成环节是不是截断了。

4.4 设计期包导致 IDE 启动崩溃

现象:装完设计期包,重启 IDE 直接闪退。原因:包依赖的其他设计期包缺失或版本冲突。解决:进 IDE 的安全模式,把刚装的包卸载,改用纯源码引用。老 IDE 上少装设计期包是保命习惯。

4.5 大文件加密内存暴涨

现象:加密几百 MB 的文件时进程内存飙升甚至 OOM。原因:一次性把整个文件读进内存再加密。解决:改成分块流式处理,每次读固定大小(比如 64KB)喂给加密上下文,最后统一收尾。加密库一般都有流式接口,别图省事用一次性方法。

注意:以上排查思路对所有 Delphi 加密库都通用,不只是这一份包。遇到问题先隔离变量,再逐项比对参数,比反复重装有效得多。

5. 进阶技巧:把加密包封装成项目内统一门面

5.1 为什么要做门面封装

直接在业务代码里到处TTMSAES.Create是维护灾难。哪天要换加密库、要加日志、要统一异常处理,你得改几十个文件。我一般会在项目里加一个薄门面单元,把 TMS 的调用收口到几个函数里,业务层只依赖门面,不依赖具体库。

unit uCryptoFacade; interface uses System.SysUtils; function EncryptText(const PlainText, KeyHex, IVHex: string): string; function DecryptText(const CipherHex, KeyHex, IVHex: string): string; function SignFile(const FileName, PrivateKeyFile: string): string; implementation uses TMS.Crypto.AES, TMS.Crypto.RSA; function EncryptText(const PlainText, KeyHex, IVHex: string): string; begin // 内部调用 TMS,外部只看到字符串进字符串出 Result := DoAESEncrypt(PlainText, KeyHex, IVHex); end; // 其余函数同理,异常在这里统一转成业务可识别的错误码 end.

逻辑说明:门面层负责参数校验、编码转换和异常包装,业务层拿到的永远是干净的字符串接口。参数说明:门面函数的参数尽量用字符串而非字节数组,降低调用方的心智负担,字节转换在门面内部完成。

5.2 用测试向量验证实现正确性

加密实现最怕「看起来能跑但结果是错的」。验证方法是用公开的标准测试向量(比如 NIST 的 AES 向量)跑一遍,比对输出。我习惯在项目里留一个测试单元,每次升级加密库都跑一遍:

测试项输入期望输出用途
AES-128 ECB标准向量已知密文验证分组算法
AES-256 CBC标准向量已知密文验证模式与 IV
SHA-256空串e3b0c442...验证哈希
HMAC-SHA256标准向量已知值验证带密钥哈希

跑通这些向量,基本能确认库的算法实现没问题,剩下的就是业务参数配置。如果向量对不上,别怀疑业务代码,先怀疑库版本或调用方式。

5.3 密钥管理的一个硬习惯

最后说个和库无关但更要命的事:密钥绝不能硬编码在源码里。我见过太多项目把 AES 密钥写成常量字符串提交进版本库,等于没加密。常见做法是把密钥放配置文件并限制文件权限,或者走环境变量注入,生产环境的私钥文件单独存放、不进代码仓库。从那以后我每次接入加密功能,都强制先过一遍「密钥从哪来、谁能读到、怎么轮换」这三个问题,答不上来就不写业务代码。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询