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?