You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 17:15:34