VB项目替换密码源为userKey时触发System.ArgumentNullException
问题解决:自动化API密钥加密解密的NullReference问题
错误原因
你遇到的System.ArgumentNullException是因为变量作用域冲突:在Form1_Load方法中,你重新声明了一个局部的userKey变量,而非给类级别声明的Public userKey As String赋值。这导致类级别的userKey始终为Nothing(空引用),当你在按钮点击事件中使用Dim password As String = userKey时,空值被传入Simple3Des构造函数,进而在TruncateHash方法调用Encoding.Unicode.GetBytes(key)时触发空引用异常。
修复与优化方案
1. 修正userKey的赋值逻辑
移除Form1_Load中的局部变量声明,直接给类级别的userKey赋值:
Public Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim sHostName As String Dim sUserName As String Dim mac As String Dim exePath As String = Application.ExecutablePath() mac = getMacAddress() ' 获取主机名/计算机名 sHostName = Environ$("computername") ' 获取当前用户名 sUserName = Environ$("username") ' 直接给类级别的userKey赋值,不再声明局部变量 userKey = sUserName & mac & exePath & sHostName Label5.Text = userKey ' 自动执行API密钥检查逻辑 CheckAndLoadApiKey() End Sub
2. 替换手动密码输入为自动生成的userKey
修改按钮点击事件,移除密码输入框,直接使用类级别的userKey,同时增加空值校验:
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click Dim plainText As String = InputBox("请输入API密钥:") If String.IsNullOrEmpty(plainText) Then MsgBox("API密钥不能为空") Return End If If String.IsNullOrEmpty(userKey) Then MsgBox("机器标识生成失败,请重启应用") Return End If Dim wrapper As New Simple3Des(userKey) Dim cipherText As String = wrapper.EncryptData(plainText) ' 将加密文件存储到用户专属目录,避免权限问题 Dim cipherPath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ApiKey.cipher") My.Computer.FileSystem.WriteAllText(cipherPath, cipherText, False) MsgBox("API密钥已加密保存") End Sub Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click Dim cipherPath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ApiKey.cipher") If Not File.Exists(cipherPath) Then MsgBox("未找到加密的API密钥,请先输入密钥") Return End If If String.IsNullOrEmpty(userKey) Then MsgBox("机器标识生成失败,请重启应用") Return End If Dim cipherText As String = My.Computer.FileSystem.ReadAllText(cipherPath) Dim wrapper As New Simple3Des(userKey) Try Dim plainText As String = wrapper.DecryptData(cipherText) MsgBox("解密后的API密钥:" & plainText) Catch ex As CryptographicException MsgBox("机器配置已变更,请重新输入API密钥") ' 删除无效的加密文件 File.Delete(cipherPath) Catch ex As Exception MsgBox("解密失败:" & ex.Message) End Try End Sub
3. 优化MAC地址获取逻辑
原代码直接取nics(1)可能导致索引越界,修改为获取第一个有效物理地址:
Function getMacAddress() As String Dim nics() As NetworkInterface = NetworkInterface.GetAllNetworkInterfaces() For Each nic In nics ' 跳过回环网卡,获取有效物理地址 If nic.NetworkInterfaceType <> NetworkInterfaceType.Loopback AndAlso Not String.IsNullOrEmpty(nic.GetPhysicalAddress().ToString()) Then Return nic.GetPhysicalAddress().ToString() End If Next ' 未找到有效MAC时返回空字符串 Return "" End Function
4. 实现自动启动校验流程
添加CheckAndLoadApiKey方法,在窗体加载时自动检查加密文件,无需用户手动操作:
Private Sub CheckAndLoadApiKey() Dim cipherPath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ApiKey.cipher") If File.Exists(cipherPath) Then If String.IsNullOrEmpty(userKey) Then MsgBox("机器标识生成失败,请重启应用") Return End If Dim cipherText As String = My.Computer.FileSystem.ReadAllText(cipherPath) Dim wrapper As New Simple3Des(userKey) Try Dim apiKey As String = wrapper.DecryptData(cipherText) MsgBox("API密钥已自动加载完成") ' 此处可将apiKey赋值给全局变量供后续使用 Catch ex As CryptographicException MsgBox("机器配置已变更,请重新输入API密钥") File.Delete(cipherPath) Button5.PerformClick() End Try Else MsgBox("未检测到API密钥,请输入") Button5.PerformClick() End If End Sub
额外安全建议
- 替换加密算法:TripleDES属于老旧算法,建议改用更安全的AES(
AesCryptoServiceProvider)。 - 随机生成IV:当前代码使用固定IV,存在安全风险,建议每次加密时生成随机IV并与密文一同存储。
- 哈希处理userKey:对生成的
userKey进行SHA256哈希,生成固定长度的密钥,避免因原始字符串过长或格式问题引发异常。 - 权限控制:避免将加密文件存储到程序安装目录,优先使用用户专属的应用数据目录(如
ApplicationData),防止UAC权限拦截。
内容的提问来源于stack exchange,提问作者Wisp
相关产品推荐
相关产品推荐

