SecItemCopyMatching在尝试在ios swift中以编程方式创建VPN连接时失败:-50

SecItemCopyMatching在尝试在ios swift中以编程方式创建VPN连接时失败:-50,swift,vpn,nevpnmanager,Swift,Vpn,Nevpnmanager,我正在尝试安装配置文件以使用Swift创建VPN连接。它创建了一个VPN连接,但我遇到以下错误,无法使用该VPN连接进行连接 SecItemCopyMatching失败:-50 keychain save-retrieve数据存在一些问题,但无法准确获取数据 代码如下: installVPNProfile(){ let server: String? = "127.0.0.1" let username: String? = "MyServer" var _: Stri

我正在尝试安装配置文件以使用Swift创建VPN连接。它创建了一个VPN连接,但我遇到以下错误,无法使用该VPN连接进行连接

SecItemCopyMatching失败:-50

keychain save-retrieve数据存在一些问题,但无法准确获取数据

代码如下:

installVPNProfile(){

    let server: String? = "127.0.0.1"
    let username: String? = "MyServer"
    var _: String? = ""
    var _: String? = ""

    // Save password & psk
    //var password_Data = KeyChain.stringToNSDATA(string:"password")
    keychain.set(("12345").data(using: .utf8)!, forKey: "VPN_PASSWORD")        
    keychain.set(("12345abcde").data(using: .utf8)!, forKey: "PSK")

    vpnManager.loadFromPreferences(completionHandler: {(_ error: Error?) -> Void in
        if error != nil {
            print("Load config failed [\(String(describing: error?.localizedDescription))]")
            return
        }
        var p: NEVPNProtocolIPSec? = (vpnManager.protocolConfiguration as? NEVPNProtocolIPSec)
        if p != nil {
            // Protocol exists.
            // If you don't want to edit it, just return here.
        }
        else {
            // create a new one.
            p = NEVPNProtocolIPSec()
        }
        // config IPSec protocol
        p?.username = username
        p?.serverAddress = server
        p?.passwordReference = self.keychain.getData("VPN_PASSWORD")        // PSK
        p?.authenticationMethod = authentication type
        p?.sharedSecretReference = self.keychain.getData("PSK")
        p?.useExtendedAuthentication = true
        p?.disconnectOnSleep = false
        self.vpnManager.protocolConfiguration = p
        self.vpnManager.localizedDescription = "VPN Demo"
        self.vpnManager.isEnabled = true
        self.vpnManager.saveToPreferences(completionHandler: {(_ error: Error?) -> Void in
            if error != nil {
                print("Save config failed [\(error?.localizedDescription)]")
            }
        })
    })

}

共享秘密引用和密码引用不应该是秘密数据本身,而应该是数据的持久性引用

设置
passwordReference
时,为其提供从
getData
函数返回的数据:

p?.passwordReference = self.keychain.getData("VPN_PASSWORD")
设置
共享secretreference
时也可以执行相同的操作。我不知道您使用的是什么代码来包装keychain代码,但是应该有一个函数返回引用,而不是数据本身。如果你的包装器代码没有这个函数,你应该使用一个键链库,或者自己创建它

通过将
kSecReturnPersistentRef
键设置为
true
,可以在查询钥匙链时获得此持久引用。从该查询返回的数据是持久引用,而不是秘密。VPN框架将在启动VPN连接时使用此引用从密钥链获取数据


查看此示例,了解如何为VPN配置文件创建和引用机密:

我使用KeychainSwift库包装n解开keychain代码。有几个库支持引用,例如有一个
dataRef()
函数