
1. 项目概述VB6与AES的“跨界”融合在当今这个数据安全被提到前所未有高度的时代加密技术早已渗透到软件开发的方方面面。然而当我们谈论现代加密算法时目光往往聚焦在Java、Python、C#、Go这些主流语言上。今天我想和大家聊一个颇具“复古”色彩但在特定历史遗留系统中又极其重要的技术点在Visual Basic 6.0中实现AES加密算法。你可能会问VB6那个二十多年前的开发工具没错正是它。尽管VB6早已退出主流舞台但全球范围内仍有海量的桌面应用、工业控制软件、财务系统甚至是一些核心业务系统依然运行在VB6构建的框架上。这些系统往往处理着敏感数据如客户信息、交易记录、工艺参数等它们的数据安全需求是真实且迫切的。直接升级或重写这些系统成本高昂、风险巨大因此在原有VB6架构下增强其安全能力就成了一种务实且高效的选择。AES高级加密标准作为目前全球公认最安全、应用最广泛的对称加密算法自然是首选。将AES算法移植到VB6环境为这些“老兵”系统披上现代化的安全铠甲正是这个VB6-AES加密算法源码项目的核心价值所在。这个项目适合所有需要维护、升级或与VB6遗留系统打交道的开发者、系统架构师和技术决策者。无论你是想为老系统增加一个安全的配置文件加密功能还是需要在VB6客户端与现代化服务端如JAVA/PHP/.NET之间建立统一的数据加密通道这份源码都能提供一个经过验证的、可靠的起点。接下来我将从设计思路、核心实现、实操集成到避坑指南为你完整拆解如何在VB6这个“特殊”环境中稳健地驾驭AES加密。2. 核心设计思路与算法选型考量在VB6中实现AES绝非简单地将C或Java代码进行语法翻译。我们需要深入理解VB6的语言特性、运行环境限制并在此基础上做出关键的设计决策。2.1 为什么是AES而不是DES或RSA首先明确选择AES的原因。对称加密算法中古老的DES因其56位密钥已不再安全3DES效率较低且逐渐被淘汰。AESRijndael算法由美国国家标准与技术研究院NIST于2001年发布支持128、192和256位三种密钥长度具有极高的安全性和良好的性能已成为事实上的全球加密标准。对于VB6程序需要保护的本地数据或进行网络传输的敏感信息AES-128通常已足够安全且加解密速度较快。若需更高安全级别可选用AES-256。非对称加密如RSA通常用于密钥交换或数字签名其加密大数据的速度远慢于对称加密因此不适合用于加密业务数据本身。在VB6场景中典型的模式是使用RSA或更简单的预共享密钥安全地传递或约定一个AES密钥后续所有数据加密均使用该AES密钥进行。本项目聚焦于AES数据加密本身这是构建安全通信或存储的基石。2.2 VB6环境下的实现挑战与策略VB6是一门基于COM的、不支持指针运算、原生数据类型有限的语言。而标准的AES实现大量依赖字节数组操作、位运算如异或、移位和查表S盒、列混合。这带来了几个核心挑战性能瓶颈VB6的数组操作和循环速度远低于C/C。纯VB6代码实现的AES其速度可能无法满足高频或大数据量加密需求。算法复杂度完整实现AES的密钥扩展、多轮加密10/12/14轮涉及大量精细的位操作纯VB6代码编写和调试难度大且容易引入不易察觉的安全漏洞如时序攻击。外部依赖与部署如何平衡性能、安全性和部署便利性针对这些挑战常见的实现策略有以下几种我们的源码项目通常采用最经典可靠的策略二策略一纯VB6算法实现。完全用VB6代码重写AES的所有步骤。优点是零外部依赖部署简单一个BAS模块就能搞定。缺点是性能最差代码量大且自行实现的加密算法若未经严格审计存在侧信道攻击等安全风险。除非有极严格的“无任何外部DLL”要求否则不推荐作为生产环境首选。策略二封装Windows CryptoAPI。这是最推荐、最稳健的方案。Windows操作系统自带的Cryptographic Service Provider (CSP) 提供了经过微软严格测试和优化的AES算法实现。VB6可以通过调用advapi32.dll中的相关API如CryptAcquireContext,CryptImportKey,CryptEncrypt等来使用它。优点非常突出性能卓越本地原生代码、安全性高微软维护符合FIPS标准、代码简洁VB6侧主要是API声明和调用逻辑。缺点是必须运行在Windows平台且需要理解CryptoAPI的编程模型。策略三封装第三方动态库DLL。可以寻找或使用C/C编写一个专注于AES的轻量级DLL然后由VB6声明并调用。这比纯VB6实现性能好比CryptoAPI更灵活可以自定义填充模式、输出格式等。但引入了额外的二进制文件依赖需要确保DLL分发的兼容性x86/x64。一个高质量的VB6-AES源码项目其核心价值往往在于它提供了一套优雅、健壮且示例丰富的CryptoAPI封装让VB6开发者能够以最小的学习成本获得企业级的安全加密能力。2.3 密钥管理与填充模式确定了实现策略还需明确两个关键参数密钥管理AES是对称加密密钥本身的安全至关重要。在VB6项目中绝对不能将密钥硬编码在代码中。常见的做法是从配置文件加密后存储或注册表中读取。由用户输入如密码再通过PBKDF2等算法导出密钥。在客户端-服务器场景中由服务器动态生成并安全下发。 源码中应包含如何安全存储和传递密钥的示例或最佳实践提示。填充模式当数据长度不是AES块大小16字节的整数倍时需要填充。CryptoAPI默认使用PKCS#7填充也称为PKCS#5填充这是一种最通用、最安全的填充方式。在与其它平台如Java的AES/CBC/PKCS5Padding交互时必须确保双方使用相同的填充模式否则解密必然失败。我们的实现需要明确指明并使用PKCS#7填充。3. 基于CryptoAPI的核心实现解析让我们深入核心看看如何利用Windows CryptoAPI在VB6中实现AES加密。我将以AES-256-CBC模式为例拆解关键步骤和代码逻辑。这里假设你已经有了一个名为modAES.bas的标准模块。3.1 API函数声明与常量定义首先需要在模块顶部声明所有需要用到的Windows API函数和常量。这是与系统交互的桥梁。 在 modAES.bas 模块顶部 Option Explicit CryptoAPI 常量 Private Const PROV_RSA_AES As Long 24 支持AES的CSP Private Const CRYPT_VERIFYCONTEXT As Long HF0000000 Private Const CALG_AES_256 As Long H6610 AES-256算法标识 Private Const CALG_SHA_256 As Long H800C SHA-256用于密钥派生如需 Private Const KP_MODE As Long 4 Private Const CRYPT_MODE_CBC As Long 1 CBC模式 Private Const KP_IV As Long 1 初始化向量参数 CryptoAPI 函数声明 Private Declare Function CryptAcquireContext Lib advapi32.dll Alias CryptAcquireContextA _ (ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, _ ByVal dwProvType As Long, ByVal dwFlags As Long) As Long Private Declare Function CryptCreateHash Lib advapi32.dll _ (ByVal hProv As Long, ByVal Algid As Long, ByVal hKey As Long, ByVal dwFlags As Long, _ ByRef phHash As Long) As Long Private Declare Function CryptHashData Lib advapi32.dll _ (ByVal hHash As Long, ByVal pbData As String, ByVal dwDataLen As Long, ByVal dwFlags As Long) As Long Private Declare Function CryptDeriveKey Lib advapi32.dll _ (ByVal hProv As Long, ByVal Algid As Long, ByVal hBaseData As Long, ByVal dwFlags As Long, _ ByRef phKey As Long) As Long Private Declare Function CryptImportKey Lib advapi32.dll _ (ByVal hProv As Long, ByVal pbData As String, ByVal dwDataLen As Long, _ ByVal hPubKey As Long, ByVal dwFlags As Long, ByRef phKey As Long) As Long Private Declare Function CryptEncrypt Lib advapi32.dll _ (ByVal hKey As Long, ByVal hHash As Long, ByVal Final As Long, ByVal dwFlags As Long, _ ByVal pbData As String, ByRef pdwDataLen As Long, ByVal dwBufLen As Long) As Long Private Declare Function CryptDecrypt Lib advapi32.dll _ (ByVal hKey As Long, ByVal hHash As Long, ByVal Final As Long, ByVal dwFlags As Long, _ ByVal pbData As String, ByRef pdwDataLen As Long) As Long Private Declare Function CryptSetKeyParam Lib advapi32.dll _ (ByVal hKey As Long, ByVal dwParam As Long, ByVal pbData As String, ByVal dwFlags As Long) As Long Private Declare Function CryptDestroyKey Lib advapi32.dll (ByVal hKey As Long) As Long Private Declare Function CryptDestroyHash Lib advapi32.dll (ByVal hHash As Long) As Long Private Declare Function CryptReleaseContext Lib advapi32.dll (ByVal hProv As Long, ByVal dwFlags As Long) As Long注意以上声明中CryptImportKey和CryptEncrypt等函数在处理字符串缓冲区时我使用了String类型并传递指针。在实际的高质量源码中为了处理任意二进制数据如图片、非ASCII文本通常会使用Byte()数组并配合StrConv、CopyMemory等函数进行精细操作避免VB6内部对字符串的自动转换破坏数据。这是VB6调用API处理加密数据的一个关键技巧。3.2 加密函数实现步骤拆解一个完整的加密过程可以封装成一个函数例如AES_EncryptString。其内部逻辑如下初始化CSP加密服务提供程序调用CryptAcquireContext获取一个CSP句柄。这是所有加密操作的起点。准备密钥情况A已有原始密钥字节如果已经有一个32字节AES-256的密钥数组我们需要将其构造成一个特殊的“简单密钥BLOB”格式然后通过CryptImportKey导入获得密钥句柄。情况B从密码派生更常见的场景是从用户密码派生密钥。这需要先使用CryptCreateHash创建一个哈希对象如SHA-256然后用CryptHashData将密码传入最后通过CryptDeriveKey从哈希值派生出AES密钥句柄。这种方式更安全但需要确保密码和盐值Salt在加密和解密端完全一致。设置加密模式与IV通过CryptSetKeyParam设置密钥的工作模式为CBC并传入一个16字节的初始化向量。IV必须是随机的且不需要保密但同一个密钥下每次加密必须使用不同的IV。通常我们将IV预置在密文头部一起传输或存储。执行加密调用CryptEncrypt。这里有个关键点函数会就地修改输入的缓冲区。你需要先分配一个足够大的缓冲区通常为原文长度 AES块大小(16)将原文复制进去并传入缓冲区的长度。函数执行后会更新pdwDataLen为实际的密文长度。清理资源按顺序销毁密钥句柄、哈希对象如果有最后释放CSP上下文。VB6没有自动垃圾回收必须手动管理这些系统资源句柄否则会导致内存或资源泄漏。3.3 解密函数实现与关键差异解密函数AES_DecryptString是加密的逆过程但有几个细节至关重要IV的提取如果加密时将IV放在了密文头部常见做法解密时首先要从密文的前16字节分离出IV。密钥的还原必须使用与加密时完全相同的密钥或密码盐来重新获取密钥句柄。设置解密IV在调用CryptDecrypt之前必须使用提取出来的IV通过CryptSetKeyParam设置到密钥句柄上。这个步骤很容易被遗漏导致解密出的前16个字节是乱码。缓冲区与长度将密文数据不含IV部分放入缓冲区调用CryptDecrypt。同样函数会就地修改缓冲区并输出解密后的数据长度。移除填充解密后需要根据PKCS#7填充规则移除末尾的填充字节才能得到原始明文。 示例函数声明高度简化版展示逻辑 Public Function AES_EncryptString(ByVal sPlainText As String, ByVal sPassword As String, ByRef sIV As String) As String Dim hProv As Long, hHash As Long, hKey As Long Dim bData() As Byte Dim lDataLen As Long ... 错误处理略 ... 1. 获取CSP If CryptAcquireContext(hProv, vbNullString, vbNullString, PROV_RSA_AES, 0) 0 Then 尝试创建新的密钥容器 If CryptAcquireContext(hProv, vbNullString, vbNullString, PROV_RSA_AES, CRYPT_NEWKEYSET) 0 Then Err.Raise ... 获取失败 End If End If 2. 从密码创建哈希并派生密钥 If CryptCreateHash(hProv, CALG_SHA_256, 0, 0, hHash) 0 Then Err.Raise ... If CryptHashData(hHash, sPassword, Len(sPassword), 0) 0 Then Err.Raise ... If CryptDeriveKey(hProv, CALG_AES_256, hHash, 0, hKey) 0 Then Err.Raise ... 3. 生成随机IV并设置CBC模式 sIV GenerateRandomIV(16) 自定义函数生成16字节随机IV If CryptSetKeyParam(hKey, KP_MODE, CRYPT_MODE_CBC, 0) 0 Then Err.Raise ... If CryptSetKeyParam(hKey, KP_IV, sIV, 0) 0 Then Err.Raise ... 4. 准备数据并加密 bData StrConv(sPlainText, vbFromUnicode) 字符串转字节数组 lDataLen UBound(bData) - LBound(bData) 1 扩展缓冲区以容纳填充 ReDim Preserve bData(0 To lDataLen 15) As Byte Dim lBufLen As Long: lBufLen UBound(bData) 1 If CryptEncrypt(hKey, 0, 1, 0, bData(0), lDataLen, lBufLen) 0 Then Err.Raise ... 5. 将IV和密文合并输出例如Base64编码 Dim bOutput() As Byte bOutput StrConv(sIV, vbFromUnicode) bData 拼接IV和密文 AES_EncryptString EncodeBase64(bOutput) 自定义Base64编码函数 6. 清理资源 If hKey 0 Then CryptDestroyKey hKey If hHash 0 Then CryptDestroyHash hHash If hProv 0 Then CryptReleaseContext hProv, 0 End Function实操心得在VB6中处理字节数组与字符串的转换是加密操作中最容易出错的地方。StrConv函数配合vbFromUnicode和vbUnicode标志是关键。对于密文这种二进制数据一定要用字节数组来保存和传递最终显示或传输时可以转换为16进制字符串或Base64字符串。直接赋值给String变量可能会导致数据损坏。4. 在VB6项目中集成与调用拿到封装好的AES模块后如何在实际的VB6工程中使用它这里有几个典型的应用场景和集成要点。4.1 场景一加密本地配置文件许多VB6程序使用INI文件或自定义文本文件存储配置。将数据库连接字符串、API密钥等敏感信息明文存储是极不安全的。 在某个表单的加载或保存配置的代码中 Private Sub SaveSecureConfig() Dim sConnectionString As String Dim sPassword As String Dim sIV As String Dim sEncrypted As String sConnectionString ServermyServer;DatabasemyDB;UidmyUser;PwdSuperSecret123; sPassword YourMasterPassword123! 这个密码应从更安全的方式获取而非硬编码 使用AES模块加密 sEncrypted AES_EncryptString(sConnectionString, sPassword, sIV) 将sEncrypted和sIV保存到配置文件或注册表 SaveSetting MyApp, Config, ConnStr, sEncrypted SaveSetting MyApp, Config, IV, sIV IV可以公开存储 End Sub Private Sub LoadSecureConfig() Dim sEncrypted As String, sIV As String Dim sPassword As String Dim sConnectionString As String sEncrypted GetSetting(MyApp, Config, ConnStr, ) sIV GetSetting(MyApp, Config, IV, ) sPassword YourMasterPassword123! If sEncrypted And sIV Then sConnectionString AES_DecryptString(sEncrypted, sPassword, sIV) 现在可以使用解密的连接字符串了 Debug.Print 解密后的连接字符串: Left(sConnectionString, 20) ... End If End Sub4.2 场景二与现代化服务端进行加密通信这是更常见的需求。你的VB6客户端需要与一个Java Spring Boot、Python Flask或.NET Core编写的Web API交互传输敏感数据。约定加密参数双方必须事先约定好算法AES-256-CBC密钥一个共享的密钥或用于派生密钥的密码和盐。严禁在客户端硬编码可通过第一次HTTPS握手由服务端动态下发并缓存。填充PKCS#7。数据格式通常客户端将IV和密文拼接然后整体进行Base64编码作为HTTP请求体或参数发送。字符编码通常使用UTF-8。VB6内部是Unicode在加密前需将字符串转换为UTF-8字节数组这需要额外的转换函数因为StrConv默认是ANSI/Unicode转换。VB6客户端发送加密数据 假设有一个调用Web API的函数 Public Function SendEncryptedData(ByVal sUrl As String, ByVal sPlainData As String) As String Dim sSharedSecret As String Dim sIV As String Dim sPayload As String Dim oHttp As Object 引用 Microsoft XML, v6.0 (MSXML2.XMLHTTP) sSharedSecret GetCachedSecretFromServer() 从安全存储中获取共享密钥 加密数据 Dim sCipherTextBase64 As String sCipherTextBase64 AES_EncryptStringToBase64(sPlainData, sSharedSecret, sIV) 这个函数内部应完成UTF-8编码 - AES加密 - (IV密文)拼接 - Base64编码 构建JSON负载示例 sPayload {iv: EncodeBase64(sIV) ,data: sCipherTextBase64 } 发送HTTPS请求 Set oHttp CreateObject(MSXML2.XMLHTTP) oHttp.Open POST, sUrl, False oHttp.setRequestHeader Content-Type, application/json oHttp.send sPayload SendEncryptedData oHttp.responseText Set oHttp Nothing End Function服务端以Java为例解密// Spring Boot 控制器示例 PostMapping(/api/receive) public ResponseEntityString receiveData(RequestBody EncryptedRequest request) { try { // request.getIv() 和 request.getData() 是Base64字符串 byte[] iv Base64.getDecoder().decode(request.getIv()); byte[] encryptedData Base64.getDecoder().decode(request.getData()); Cipher cipher Cipher.getInstance(AES/CBC/PKCS5Padding); SecretKeySpec keySpec new SecretKeySpec(sharedSecretKey.getBytes(StandardCharsets.UTF_8), AES); IvParameterSpec ivSpec new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); byte[] decryptedBytes cipher.doFinal(encryptedData); String plainText new String(decryptedBytes, StandardCharsets.UTF_8); // 处理明文数据 plainText... return ResponseEntity.ok(Success); } catch (Exception e) { // 常见错误BadPaddingException (填充错误密钥或IV不对) // IllegalBlockSizeException return ResponseEntity.status(400).body(Decrypt Error: e.getMessage()); } }4.3 模块的工程化封装建议为了让AES模块更易用、更健壮建议进行如下封装统一入口提供一个主要的类模块如clsAESCrypto或一组标准模块函数对外暴露简单的Encrypt和Decrypt方法。集中错误处理在模块内部使用统一的错误处理机制将CryptoAPI返回的错误码通过GetLastErrorAPI获取转换为有意义的VB6错误信息并抛出。支持多种输入输出提供重载函数支持String、Byte()数组的加密解密以及输出为16进制字符串或Base64字符串。密钥管理抽象将密钥获取逻辑从密码派生、从文件读取、从内存获取抽象出来使核心加密函数更专注于算法本身。5. 常见问题、调试与安全强化即使有了源码在集成和使用过程中也一定会遇到各种问题。以下是我在实际项目中总结的常见坑点和解决方案。5.1 跨平台解密失败问题排查清单当你的VB6加密的数据在Java、C#、Python等服务端解密失败时请按以下顺序排查问题现象可能原因排查步骤与解决方案解密后前16字节乱码后面正确IV未设置或设置不正确。解密时没有使用加密时生成的IV或者设置IV的时机不对应在CryptDecrypt之前设置。1. 确认VB6代码将IV与密文一起保存/传输。2. 确认服务端解密代码正确地从完整密文中分离出IV。3. 确认服务端在初始化Cipher并调用doFinal解密之前已将IV设置到算法参数中。解密抛出BadPaddingException密钥、填充模式或数据块不匹配。这是最常见错误。1.密钥一致性确保两端使用的密钥字节完全一致。检查VB6的密钥生成/导入逻辑和服务端的密钥加载逻辑。如果使用密码确保密码字符串和盐值Salt完全一致并且字符编码UTF-8/ANSI也一致。2.填充模式确保服务端使用的是PKCS5Padding对应PKCS#7。3.数据完整性确认Base64解码正确传输过程中密文没有被截断或修改。解密出的明文是乱码字符编码问题。VB6内部是Unicode而服务端可能期望UTF-8或其它编码。在VB6加密前将字符串显式转换为UTF-8字节数组。可以使用ADODB.Stream对象或自定义函数进行精确的UTF-8编码。同样解密后得到UTF-8字节数组也要正确解码回VB6的Unicode字符串。CryptDecrypt返回错误0x80090005CryptoAPI内部错误通常意味着密钥句柄无效或数据损坏。1. 检查密钥导入或派生过程是否成功。2. 检查传入CryptDecrypt的密文数据缓冲区是否正确长度是否包含填充。3. 确保在解密前已正确设置了IV和CBC模式。调试技巧在开发阶段可以添加详细的日志。在VB6端将加密前的明文、使用的密钥可输出其16进制摘要而非明文、生成的IV、加密后的密文Base64都打印或记录到文件。在服务端同样记录接收到的IV和密文。对比两端的日志可以快速定位不一致的环节。一个有用的方法是先用一个固定的、简单的字符串如Hello, AES!和固定的密钥/IV进行测试确保基础流程通顺。5.2 VB6特有的性能与资源陷阱句柄泄漏这是VB6调用API最经典的陷阱。每一个成功的CryptAcquireContext、CryptCreateHash、CryptImportKey调用都必须有对应的CryptDestroy...和CryptReleaseContext来释放。务必在函数的错误处理分支和正常退出分支都确保资源被释放。建议使用On Error GoTo统一处理。字符串与二进制数据混淆如前所述密文是二进制数据。如果你错误地将其当作普通字符串处理比如用Mid$,Left$函数或直接显示在TextBox中可能会因为遇到Chr(0)空字符而截断或者被VB6的Unicode转换破坏。始终使用Byte()数组作为中间载体。Base64编码解码VB6没有内置Base64支持。你需要自己实现或引用一个可靠的Base64模块如通过MSXML2.DOMDocument的nodeTypedValue属性转换。确保编解码函数能正确处理二进制数据。5.3 安全强化建议密钥存储这是安全链条中最弱的一环。绝对不要将密钥硬编码在EXE或DLL中。可以考虑使用Windows Data Protection API (DPAPI)这是Windows为本地机器或当前用户加密数据提供的API。可以将加密后的密钥用DPAPI再加密一次后存储。这样密钥的解密依赖于机器或用户上下文提高了便携性攻击的难度。从高权限配置源获取从需要管理员权限才能访问的注册表路径或文件中读取密钥。动态获取从安全的中央服务器通过认证后动态获取会话密钥。使用经过验证的源码从信誉良好的来源获取VB6-AES源码并尽可能理解其每一行代码。自行实现的加密算法很难保证没有漏洞。结合HTTPS网络传输时AES加密确保了数据的机密性但还需要完整性防篡改和身份验证防冒充。务必在TLSHTTPS的通道上进行传输TLS协议本身提供了这些保障。AES不能替代TLS它们是互补的。定期更换密钥对于长期使用的系统应建立密钥轮换机制。6. 从源码到实践一个完整的配置加密示例让我们通过一个完整的、可运行的示例将上述所有知识点串联起来。这个示例演示如何加密一个应用程序的设置并安全地保存到注册表。首先我们需要一个完整的modAES.bas模块基于CryptoAPI封装。由于篇幅这里只列出核心函数调用和关键逻辑完整的错误处理和辅助函数如Base64、字节数组操作需要你从可靠的源码项目中获取。 modAES.bas - 核心函数摘要 Public Function AES_EncryptBytesToBase64(bInput() As Byte, bKey() As Byte, bIV() As Byte) As String 输入明文字节数组、密钥字节数组、IV字节数组 输出Base64编码的字符串已包含IV 内部逻辑设置CBC模式和IV - 加密 - 拼接IV与密文 - Base64编码 End Function Public Function AES_DecryptBytesFromBase64(sBase64 As String, bKey() As Byte) As Byte() 输入Base64字符串、密钥字节数组 输出解密后的明文字节数组 内部逻辑Base64解码 - 分离IV和密文 - 设置CBC模式和IV - 解密 - 移除PKCS#7填充 End Function Public Function DeriveKeyFromPassword(sPassword As String, Optional bSalt() As Byte) As Byte() 使用PBKDF2或类似算法从密码和盐派生固定长度的密钥字节数组 这是安全存储密码的关键避免直接使用简单哈希 End Function接下来在主窗体或一个工具类中我们使用这些函数 在 frmMain.frm 或 clsSettings.cls 中 Private Const REG_PATH As String Software\MyCompany\MyApp\SecureSettings Private Const VALUE_ENCRYPTED_CONFIG As String EncryptedConfig Private Const VALUE_KEY_SALT As String KeySalt 存储盐值公开无害 Public Sub SaveSecureSettings(ByVal sServer As String, ByVal sUser As String, ByVal sPassword As String) On Error GoTo ErrorHandler Dim sPlainSettings As String Dim bKey() As Byte, bSalt(15) As Byte 16字节的盐 Dim bIV() As Byte Dim sMasterPassword As String Dim sEncryptedBase64 As String 1. 构建JSON格式的明文配置 sPlainSettings {server: sServer ,user: sUser ,pass: sPassword } 2. 获取或生成主密码和盐此处简化实际应从更安全的地方获取密码 sMasterPassword GetMasterPasswordFromUser() 弹窗让用户输入主密码 If sMasterPassword Then Exit Sub 生成随机盐首次运行时或从注册表读取已有的盐 If IsFirstRun() Then 调用CryptoAPI的 CryptGenRandom 生成随机盐 Call CryptGenRandom(GetCSPHandle(), 16, bSalt(0)) SaveToRegistry VALUE_KEY_SALT, bSalt 保存盐值 Else bSalt LoadFromRegistry(VALUE_KEY_SALT) End If 3. 从密码和盐派生密钥 bKey DeriveKeyFromPassword(sMasterPassword, bSalt) 4. 生成随机IV并加密 bIV GenerateRandomBytes(16) 生成16字节随机IV Dim bPlainBytes() As Byte bPlainBytes StrConv(sPlainSettings, vbFromUnicode) 转换为ANSI/UTF-8字节数组需根据情况调整 sEncryptedBase64 AES_EncryptBytesToBase64(bPlainBytes, bKey, bIV) 5. 将加密后的Base64字符串保存到注册表 SaveToRegistry VALUE_ENCRYPTED_CONFIG, sEncryptedBase64 MsgBox 配置已安全保存。, vbInformation Exit Sub ErrorHandler: MsgBox 保存配置时出错: Err.Description, vbCritical End Sub Public Sub LoadSecureSettings(ByRef sServer As String, ByRef sUser As String, ByRef sPassword As String) On Error GoTo ErrorHandler Dim sEncryptedBase64 As String Dim bKey() As Byte, bSalt() As Byte Dim sMasterPassword As String Dim bDecryptedBytes() As Byte Dim sPlainSettings As String Dim vSettings As Variant 1. 从注册表读取加密数据和盐 sEncryptedBase64 LoadFromRegistry(VALUE_ENCRYPTED_CONFIG) If sEncryptedBase64 Then Exit Sub 无保存的配置 bSalt LoadFromRegistry(VALUE_KEY_SALT) 2. 获取主密码 sMasterPassword GetMasterPasswordFromUser() If sMasterPassword Then Exit Sub 3. 派生密钥并解密 bKey DeriveKeyFromPassword(sMasterPassword, bSalt) bDecryptedBytes AES_DecryptBytesFromBase64(sEncryptedBase64, bKey) 4. 字节数组转回字符串并解析JSON此处简化实际可用VB-JSON解析器 sPlainSettings StrConv(bDecryptedBytes, vbUnicode) 假设我们有一个简单的解析函数 vSettings ParseSimpleJSON(sPlainSettings) 返回字典或数组 sServer vSettings(server) sUser vSettings(user) sPassword vSettings(pass) MsgBox 配置加载成功。, vbInformation Exit Sub ErrorHandler: 特别处理解密失败可能是密码错误 If Err.Number YOUR_DECRYPT_ERROR_CODE Then 需要定义 MsgBox 主密码错误或配置已损坏。, vbExclamation Else MsgBox 加载配置时出错: Err.Description, vbCritical End If End Sub 辅助函数生成随机字节 Private Function GenerateRandomBytes(ByVal lLength As Long) As Byte() Dim bBytes() As Byte ReDim bBytes(0 To lLength - 1) As Byte 调用 CryptGenRandom 填充 bBytes 数组 ... (具体API调用略) ... GenerateRandomBytes bBytes End Function这个示例展示了相对完整的流程使用用户输入的主密码和随机盐派生密钥用随机IV加密配置JSON格式并将密文和盐公开保存。加载时用户再次输入主密码结合盐派生相同密钥进行解密。盐的加入使得针对常用密码的彩虹表攻击失效大大增强了安全性。最后我想强调的是在VB6这类传统技术栈中实施现代加密更像是一场“外科手术式的升级”。它不需要你推翻重来而是在关键的数据通道上精准地植入安全模块。选择经过实战检验的CryptoAPI封装方案透彻理解密钥管理、编码和模式设置这些细节你就能让那些承载着重要业务的“老系统”继续安全、稳定地运行下去从容应对当下的安全挑战。