Utilizing Keychain Services with Swift 5.9

Hello,

I'm near-brand new to writing in Swift and am attempting to write a simple VPN configuration to start an existing VPN in-app for a mobile app I'm developing for the company I work for. We're writing this in Swift in hopes of converting them to C# eventually for the mobile app's end product.

So I'm attempting to set VPN configurations using a NEVPNProtocolIKEv2() type, and when it comes to setting the server address, remote identifier, and username, it seems pretty straightforward.

However, when I try to set a password reference, I'm failing to figure out how to do so in a straight forward way. I've tried several methods from the docs and continuously yield no results, so I wanted to ask if I was doing something wrong in the following code (most of which is commented out, but indicated by single line comments where the attempts were).

/** @class VPN contains all of the configuration and handling for enacting a VPN connection */
class VPN {
    // Initialize `manager` variable with `NEVPNManager` object using @method `shared()`
    let manager = NEVPNManager.shared()
    /** @variable vpnLoadHandler handles loading the VPN and error catching? */
    private var vpnLoadHandler:
    (Error?) -> Void {
        return {
            (error:Error?) in
            if ((error) != nil) {
                print("Load VPN Configurations failed...")
                return;
            }
            // Initialize and assign `p` as `NEVPNProtocolIKEv2()` interface
            let p = NEVPNProtocolIKEv2()
            // Assign property values for the IKEv2 VPN
            p.serverAddress = "0.0.0.0"
            p.remoteIdentifier = "abc"
            p.username = "iosUser"
            // Assign string `pass` with string value of intended password
            let pass = "password"
            // Assign string `key` with string value of intended key
            let key = "pwd"
            // Create an add query to encode password as `Data` instance
            var query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                                        kSecAttrGeneric as String: key,
                                        kSecValueData as String: pass]
            // Add the item to `passKeyValue` using `SecAddItem`
            let passKeyValue = SecItemAdd(query as CFDictionary, nil)
                // ALTERNATIVE VALUE ASSIGNMENT
            // let passKeyValue = SecItemCopyMatching(query as CFDictionary, nil)
            // Initiate search to access password from query
                // ATTEMPT 1
            /*
             var item: CFTypeRef?
             guard let existingItem = item as? [String: Any],
             let passwordData = existingItem[kSecValueData as String] as? Data,
             let password = passwordData
             else {
             print("Keychain failed...")
             }
             */
                // ATTEMPT 2
            /*
             var error: Unmanaged<CFError>?
             guard let data = SecKeyCopyExternalRepresentation(passKeyValue, &error) as Data else {
             throw error!.takeRetainedValue() as Error
             }
             */
                // ATTEMPT 3
            /*
            var error: Unmanaged<CFError>?
            guard let pkData = SecKeyCreateWithData(data as CFData,
                                                    query as CFDictionary,
                                                    &error) else {
                throw error!.takeRetainedValue() as Error
            }
             */
        }
    }
}

I'm just a little lost because as of a year ago, other similar code that I've referenced uses conventions of:

let kcs = KeychainService();
            kcs.save(key: "SHARED", value: "MY_SHARED_KEY")
            kcs.save(key: "VPN_PASSWORD", value: "MY_PASSWORD"

Why has it changed? How would I go about achieving the same thing?

The Personal VPN API is a bit of an outlier because it relies on persistent references. Most keychain examples you’ll find don’t use those, so they’re hard to adapt to this scenario. However, in this post you’ll find a snippet that’s exactly for this scenario.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Utilizing Keychain Services with Swift 5.9
 
 
Q