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

时间:2017-08-08 11:45:53

标签: swift vpn nevpnmanager

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

  

SecItemCopyMatching失败:-50

钥匙串保存检索数据存在一些问题,但未完全准确。

以下是代码:

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)]")
            }
        })
    })

}

1 个答案:

答案 0 :(得分:1)

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

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

p?.passwordReference = self.keychain.getData("VPN_PASSWORD")

设置sharedSecretReference时也会这样做。我不知道你使用的代码是包装密钥链代码,但是应该有一个返回引用的函数,而不是数据本身。如果你的包装器代码没有这个功能,你应该使用一个支持它的Keychain库,或者自己创建它。

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

查看此示例如何创建和引用VPN配置文件的机密:http://blog.moatazthenervous.com/create-a-key-chain-for-apples-vpn/