Create Personal VPN connection using NEVPNManager - ios

I am trying to create VPN connection in my app. I go through this link
https://developer.apple.com/documentation/networkextension/nevpnmanager
but did not find any official code to use NEVPNManager and even not found any tutorial to use this NEVPNManager.
I am new to VPN concept and don't know that much about it. so Can anyone give some solutions?

Here is a IKEv2 configuration of VPN using Network Extension (Without shared key and certificate) in Swift 4.2:
final class VPNHandler {
let vpnManager = NEVPNManager.shared()
func initVPNTunnelProviderManager() {
print("CALL LOAD TO PREFERENCES...")
self.vpnManager.loadFromPreferences { (error) -> Void in
if((error) != nil) {
print("VPN Preferences error: 1")
} else {
let IKEv2Protocol = NEVPNProtocolIKEv2()
IKEv2Protocol.username = vpnUser.username
IKEv2Protocol.serverAddress = vpnServer.serverID //server tunneling Address
IKEv2Protocol.remoteIdentifier = vpnServer.remoteID //Remote id
IKEv2Protocol.localIdentifier = vpnUser.localID //Local id
IKEv2Protocol.deadPeerDetectionRate = .low
IKEv2Protocol.authenticationMethod = .none
IKEv2Protocol.useExtendedAuthentication = true //if you are using sharedSecret method then make it false
IKEv2Protocol.disconnectOnSleep = false
//Set IKE SA (Security Association) Params...
IKEv2Protocol.ikeSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256
IKEv2Protocol.ikeSecurityAssociationParameters.integrityAlgorithm = .SHA256
IKEv2Protocol.ikeSecurityAssociationParameters.diffieHellmanGroup = .group14
IKEv2Protocol.ikeSecurityAssociationParameters.lifetimeMinutes = 1440
//IKEv2Protocol.ikeSecurityAssociationParameters.isProxy() = false
//Set CHILD SA (Security Association) Params...
IKEv2Protocol.childSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256
IKEv2Protocol.childSecurityAssociationParameters.integrityAlgorithm = .SHA256
IKEv2Protocol.childSecurityAssociationParameters.diffieHellmanGroup = .group14
IKEv2Protocol.childSecurityAssociationParameters.lifetimeMinutes = 1440
let kcs = KeychainService()
//Save password in keychain...
kcs.save(key: "VPN_PASSWORD", value: vpnUser.password)
//Load password from keychain...
IKEv2Protocol.passwordReference = kcs.load(key: "VPN_PASSWORD")
self.vpnManager.protocolConfiguration = IKEv2Protocol
self.vpnManager.localizedDescription = "Safe Login Configuration"
self.vpnManager.isEnabled = true
self.vpnManager.isOnDemandEnabled = true
//print(IKEv2Protocol)
//Set rules
var rules = [NEOnDemandRule]()
let rule = NEOnDemandRuleConnect()
rule.interfaceTypeMatch = .any
rules.append(rule)
print("SAVE TO PREFERENCES...")
//SAVE TO PREFERENCES...
self.vpnManager.saveToPreferences(completionHandler: { (error) -> Void in
if((error) != nil) {
print("VPN Preferences error: 2")
} else {
print("CALL LOAD TO PREFERENCES AGAIN...")
//CALL LOAD TO PREFERENCES AGAIN...
self.vpnManager.loadFromPreferences(completionHandler: { (error) in
if ((error) != nil) {
print("VPN Preferences error: 2")
} else {
var startError: NSError?
do {
//START THE CONNECTION...
try self.vpnManager.connection.startVPNTunnel()
} catch let error as NSError {
startError = error
print(startError.debugDescription)
} catch {
print("Fatal Error")
fatalError()
}
if ((startError) != nil) {
print("VPN Preferences error: 3")
//Show alert here
print("title: Oops.., message: Something went wrong while connecting to the VPN. Please try again.")
print(startError.debugDescription)
} else {
//self.VPNStatusDidChange(nil)
print("Starting VPN...")
}
}
})
}
})
}
} //END OF .loadFromPreferences //
}
//MARK:- Connect VPN
static func connectVPN() {
VPNHandler().initVPNTunnelProviderManager()
}
//MARK:- Disconnect VPN
static func disconnectVPN() {
VPNHandler().vpnManager.connection.stopVPNTunnel()
}
//MARK:- check connection staatus
static func checkStatus() {
let status = VPNHandler().vpnManager.connection.status
print("VPN connection status = \(status.rawValue)")
switch status {
case NEVPNStatus.connected:
print("Connected")
case NEVPNStatus.invalid, NEVPNStatus.disconnected :
print("Disconnected")
case NEVPNStatus.connecting , NEVPNStatus.reasserting:
print("Connecting")
case NEVPNStatus.disconnecting:
print("Disconnecting")
default:
print("Unknown VPN connection status")
}
}
}
Code for keychain:
//MARK:- Variables for keychain access
// Identifiers
let serviceIdentifier = "MySerivice"
let userAccount = "authenticatedUser"
let accessGroup = "MySerivice"
// Arguments for the keychain queries
var kSecAttrAccessGroupSwift = NSString(format: kSecClass)
let kSecClassValue = kSecClass as CFString
let kSecAttrAccountValue = kSecAttrAccount as CFString
let kSecValueDataValue = kSecValueData as CFString
let kSecClassGenericPasswordValue = kSecClassGenericPassword as CFString
let kSecAttrServiceValue = kSecAttrService as CFString
let kSecMatchLimitValue = kSecMatchLimit as CFString
let kSecReturnDataValue = kSecReturnData as CFString
let kSecMatchLimitOneValue = kSecMatchLimitOne as CFString
let kSecAttrGenericValue = kSecAttrGeneric as CFString
let kSecAttrAccessibleValue = kSecAttrAccessible as CFString
class KeychainService: NSObject {
func save(key:String, value:String) {
let keyData: Data = key.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue), allowLossyConversion: false)!
let valueData: Data = value.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue), allowLossyConversion: false)!
let keychainQuery = NSMutableDictionary();
keychainQuery[kSecClassValue as! NSCopying] = kSecClassGenericPasswordValue
keychainQuery[kSecAttrGenericValue as! NSCopying] = keyData
keychainQuery[kSecAttrAccountValue as! NSCopying] = keyData
keychainQuery[kSecAttrServiceValue as! NSCopying] = "VPN"
keychainQuery[kSecAttrAccessibleValue as! NSCopying] = kSecAttrAccessibleAlwaysThisDeviceOnly
keychainQuery[kSecValueData as! NSCopying] = valueData;
// Delete any existing items
SecItemDelete(keychainQuery as CFDictionary)
SecItemAdd(keychainQuery as CFDictionary, nil)
}
func load(key: String)->Data {
let keyData: Data = key.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue), allowLossyConversion: false)!
let keychainQuery = NSMutableDictionary();
keychainQuery[kSecClassValue as! NSCopying] = kSecClassGenericPasswordValue
keychainQuery[kSecAttrGenericValue as! NSCopying] = keyData
keychainQuery[kSecAttrAccountValue as! NSCopying] = keyData
keychainQuery[kSecAttrServiceValue as! NSCopying] = "VPN"
keychainQuery[kSecAttrAccessibleValue as! NSCopying] = kSecAttrAccessibleAlwaysThisDeviceOnly
keychainQuery[kSecMatchLimit] = kSecMatchLimitOne
keychainQuery[kSecReturnPersistentRef] = kCFBooleanTrue
var result: AnyObject?
let status = withUnsafeMutablePointer(to: &result) { SecItemCopyMatching(keychainQuery, UnsafeMutablePointer($0)) }
if status == errSecSuccess {
if let data = result as! NSData? {
if let value = NSString(data: data as Data, encoding: String.Encoding.utf8.rawValue) {
//print(value)
}
return data as Data;
}
}
return "".data(using: .utf8)!;
}
}

This tutorial help me to create VPN connection.
http://blog.moatazthenervous.com/create-a-vpn-connection-with-apple-swift/
VPN file for connection and disconnection
import Foundation
import NetworkExtension
// MARK: - NEVPNManager
// MARK: -
private var vpnLoadHandler: (Error?) -> Void { return
{ (error:Error?) in
if ((error) != nil) {
print("Could not load VPN Configurations")
self.removeToast()
return;
}
self.showToast(msg: STRINGVALUES.kCreatingConnection)
//VPN connection via Username password
let p = NEVPNProtocolIPSec()
let kcs = KeychainService()
p.authenticationMethod = NEVPNIKEAuthenticationMethod.sharedSecret
//For the security purpose added word xyz in password .so it should be remove while connecting
if self.selectedSever != nil{
self.selectedSever?.password = (self.selectedSever?.password.replacingOccurrences(of: "xyz", with: ""))!
p.username = self.selectedSever?.userName
p.serverAddress = self.selectedSever?.serverAddress
kcs.save(key: "SHARED", value: (self.selectedSever?.password)!)
kcs.save(key: "VPN_PASSWORD", value: (self.selectedSever?.password)!)
p.sharedSecretReference = kcs.load(key: STRINGVALUES.kShared)
p.passwordReference = kcs.load(key: STRINGVALUES.kVPN_Pswd)
p.useExtendedAuthentication = true
p.disconnectOnSleep = false
// Check for free subscriber
if self.selectedSever?.serverType == STRINGVALUES.VIP.lowercased() && !Singleton.checkForPaidReciept(){
self.disconnectVPN()
Helper.showAlert(sender: self, title: STRINGVALUES.AppName, message: AlertMessage.kValidateSubscription)
return
}
self.vpnManager.protocolConfiguration = p
self.vpnManager.localizedDescription = STRINGVALUES.AppName
self.vpnManager.isEnabled = true
self.vpnManager.saveToPreferences(completionHandler: self.vpnSaveHandler)
}else{
}
}
}
private var vpnSaveHandler: (Error?) -> Void { return
{ (error:Error?) in
if (error != nil) {
print("Could not save VPN Configurations")
self.removeToast()
return
} else {
do {
try self.vpnManager.connection.startVPNTunnel()
} catch let error {
print("Error starting VPN Connection \(error.localizedDescription)");
self.removeToast()
}
}
}
//self.vpnlock = false
}
public func connectVPN() {
//For no known reason the process of saving/loading the VPN configurations fails.On the 2nd time it works
do {
try self.vpnManager.loadFromPreferences(completionHandler: self.vpnLoadHandler)
} catch let error {
print("Could not start VPN Connection: \(error.localizedDescription)" )
self.removeToast()
}
}
public func disconnectVPN() ->Void {
vpnManager.connection.stopVPNTunnel()
}
func vpnConnectionStatusChanged(){
let status = self.vpnManager.connection.status
print("VPN connection status = \(status)")
switch status {
case NEVPNStatus.connected:
showToast(msg: STRINGVALUES.kConnected)
case NEVPNStatus.invalid, NEVPNStatus.disconnected :
showToast(msg: STRINGVALUES.kDisconnected)
case NEVPNStatus.connecting , NEVPNStatus.reasserting:
showToast(msg: STRINGVALUES.kConnecting)
case NEVPNStatus.disconnecting:
showToast(msg: STRINGVALUES.kDisconnecting)
default:
print("Unknown VPN connection status")
}
}

Related

In-App Purchase working or not when remove my account from iPhone?

I am using auto renewal subscription In-App Purchase in my application. I want to know what happened when i remove my apple account after purchase in iPhone. in app purchase is worked or not ?? I am using sandbox environment.
If not so how to know in-app apple account was removed ??
I have try to verifying the receipt and checked the in-app purchased is expire or not, but after remove apple account i always get receipt response true.
here is my get receipt request code :
#objc func loadreceipt() {
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
if UD.getS(receiptdata).isEmpty == false {
Api.inAppPurchasecall(.receiptVarify(rdata: UD.getS(receiptdata), excludeInclude: true)) { response, error in
if error == nil {
self.checkresponse(response: response as! Map)
}else{
print(error)
}
}
}else{
do {
let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
let receiptString = receiptData.base64EncodedString(options: [])
Api.inAppPurchasecall(.receiptVarify(rdata: receiptString, excludeInclude: true)) { response, error in
if error == nil {
self.checkresponse(response: response as! Map)
}else{
print(error)
}
}
}
catch { print("Couldn't read receipt data with error: " + error.localizedDescription) }
}
}else{
requestrefreshreceipt = SKReceiptRefreshRequest()
requestrefreshreceipt?.delegate = self
requestrefreshreceipt?.start()
}
}
receipt response code :
func checkresponse(response : Map) {
if let rdata = response["latest_receipt"] as? String {
UD.setS(receiptdata, rdata)
}
if let latestreceiptinfo = response["latest_receipt_info"] as? [Map] {
if let lastinfo = latestreceiptinfo.first {
if let expiredate = lastinfo["expires_date"] as? String, let edate = Formatter.customDate.date(from: expiredate) {
if let strEdate = gmtToLocal(date: edate) {
self.nextBillingDate = strEdate
}
}
if let expiredate = lastinfo["purchase_date"] as? String, let edate = Formatter.customDate.date(from: expiredate) {
if let strEdate = gmtToLocal(date: edate) {
self.lastBillingDate = strEdate
}
}
if let expiretime = lastinfo["expires_date_ms"] as? String, let doubleexpiretime = Double(expiretime) {
expireTimeStamp = doubleexpiretime/1000
let currenttimestamp = Date().timeIntervalSince1970
if let etimestamp = expireTimeStamp {
if etimestamp > currenttimestamp {
UD.setS(AppConst.SUBSCRIPTION_STATUS, "true")
NotificationCenter.default.post(name: NSNotification.Name(rawValue: kRefreshServices), object:nil)
}else{
UD.setS(AppConst.SUBSCRIPTION_STATUS, "false")
NotificationCenter.default.post(name: NSNotification.Name(rawValue: kRefreshServices), object:nil)
if let expiredate = lastinfo["expires_date"] as? String, let edate = Formatter.customDate.date(from: expiredate) {
if let root = APP_DELEGATE.window?.rootViewController {
if let strEdate = gmtToLocal(date: edate) {
}
}
}
}
}
}
}
}
}

How to get server address and remoteIdentifier?

I am able to save VPN configuration. Please tell me how to make the server address variable or get a server address and what is the remote identifier for?
I have used this example for reference: Connect to a VPN with certificate - iOS/Swift
How can I solve this?
func connectVPN(){
do {
if let file = URL(string: "example.com") {
let data = try Data(contentsOf: file)
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let object = json as? [String: String] {
// json is a dictionary
var data_VPN = object["VPN_data"]!
//print("Donebro:\(data_VPN)")
let certificate = data_VPN
let nsdata = certificate.data(using: .utf8)
let base64EncodedData = nsdata!.base64EncodedData()
print("base64StoreData:\(nsdata!)")
print("base64StoreNewData:\(base64EncodedData)")
var vpnManager = NEVPNManager.shared()
vpnManager.loadFromPreferences { error in
if vpnManager.`protocol` == nil{
let newIPSec = NEVPNProtocolIPSec()
newIPSec.serverAddress = ""
newIPSec.localIdentifier = ""
newIPSec.remoteIdentifier = ""
newIPSec.useExtendedAuthentication = true
newIPSec.identityData = base64EncodedData as! Data
newIPSec.authenticationMethod = NEVPNIKEAuthenticationMethod.certificate
print("VPNDATA:\(newIPSec)")
if #available(iOS 9, *) {
vpnManager.protocolConfiguration = newIPSec
} else {
vpnManager.`protocol` = newIPSec
}
vpnManager.isEnabled = true
vpnManager.saveToPreferences(completionHandler: { (error) -> Void in
if ((error) != nil) {
print("VPN Preferences error: 2")
}
else {
vpnManager.loadFromPreferences(completionHandler: { (error) in
if ((error) != nil) {
print("VPN Preferences error: 2")
}
else {
var startError: NSError?
do {
try vpnManager.connection.startVPNTunnel()
}
catch let error as NSError {
startError = error
print(startError)
}
catch {
print("Fatal Error")
fatalError()
}
if ((startError) != nil) {
print("VPN Preferences error: 3")
let alertController = UIAlertController( title: "Oops..", message: "Something went wrong while connecting to the VPN. Please try again.", preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction( UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.default,handler: nil))
self.present(alertController, animated: true, completion: nil)
print(startError)
}
else {
//VPNStatusDidChange(nil)
print("Start VPN")
}
}
})
}
})
}
} else if let object = json as? [Any] {
// json is an array
for anItem in object as! [Dictionary<String, AnyObject>] {
let industryName = anItem["VPN_data"] as! String
}
} else {
print("JSON is invalid")
}
} else {
print("no file")
}
} catch {
print(error.localizedDescription)
}
}
}

How to Sync Microsoft Exchange account in ios

How to sync Microsoft Exchange Account, using Exchange Web Services in iOS app. Its discussed here:
I tried this - http://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/OUC-B304#fbid=
Tried this so far -
func connectToServer() -> Bool {
let basicURL: String = "http://\(self.servername)/autodiscover/autodiscover.xml"
let poxOLKAutoDRequest = "<?xml version=\"1.0\"encoding=\"utf-8\"?> <Autodiscover xmlns=\"http://schemas.microsoft.com/exchange/autodiscover/outlook.requestschema/2006\" <Request> <EmailAddress>\(usernmTF.text!)</EmailAddress> <AcceptableResponseSchema>http://schemas.microsoft.com/exhange/autodiscover/outlook/responseschema/2005a</AcceptableResponseSchema> </Request> </Autodiscover>"
let url: URL = URL.init(string: basicURL)!
//AutoD expects an HTTP POST with request body
let request: ASIHTTPRequest = ASIHTTPRequest.init(url: url)
request.username = self.usernmTF.text!
request.password = self.passwdTF.text!
request.requestHeaders = ["Content-Type": "text/xml; charset=utf-8"]
request.timeOutSeconds = 90
request.shouldUseRFC2616RedirectBehaviour = true
request.appendPost(poxOLKAutoDRequest.data(using: .utf8)!)
request.startSynchronous()
let error = request.error
if (!(error != nil)) {
let response = request.responseData()
// let doc = XMLParser.init(data: response!)
var doc = GDataXMLDocument()
do {
doc = try GDataXMLDocument.init(data: response!)
} catch {
print(error)
}
if doc != nil {
let ns: NSDictionary = ["rs": "http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006", "ol": "http://schemas.microsoft.com/exchange/autodiscover//outlookresponseschema/2006a"]
let userData = NSArray()
let protocolData = NSArray()
do {
let Data = try doc.nodes(forXPath: "//rs:Autodiscover/ol:Response/ol:User/ol:AutoDiscoverSMTPAddress", namespaces: ns as! [AnyHashable : Any])
_ = self.userData(data: Data)
} catch {
print(error)
}
if error == nil {
let userEmail: GDataXMLElement = userData.object(at: 0) as! GDataXMLElement
print(userEmail.stringValue())
}
do {
let Data = try doc.nodes(forXPath: "//rs:Autodiscover/ol:Response/ol:Account/ol:Protocol/[ol:Type=\"EXPR\"]", namespaces: ns as! [AnyHashable : Any])
self.protocolData(pr_Data: Data)
} catch {
print(error)
}
if error == nil {
for proto in protocolData{
let aProto = proto as! GDataXMLElement
let asURLs = aProto.elements(forName: "ASUrl")! as NSArray
if asURLs.count > 0 {
let theURL: GDataXMLElement = asURLs.object(at: 0) as! GDataXMLElement
self.setServerUrl(url: URL.init(string: theURL.stringValue())!)
}
}
}
}
return true
}
return false
}
After run this getting erring 404.
Is there any better solution to do this, Please guide.
Thanks.

How to get contact (firstname, lastname, contactid, number)

I have used AddessBook library (for ios8) to get all contact (firstname, lastname, contactId, all phone number). it worked perfect on simulitor.
my code:
private func getContacts()->[Person] {
var peapleOfContact: [Person] = []
if !self.determineStatus() {
return peapleOfContact
}
if let people = ABAddressBookCopyArrayOfAllPeople(self.adbk)?.takeRetainedValue() as? NSArray {
for person in people{
let contactID = ABRecordGetRecordID(person)
let firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty).takeRetainedValue() as! String
let lastName = ABRecordCopyValue(person, kABPersonLastNameProperty).takeRetainedValue() as! String
let personOfContact = Person(id: String(contactID), firstName: firstName, lastName: lastName)
let numbers:ABMultiValue = ABRecordCopyValue(person, kABPersonPhoneProperty).takeRetainedValue()
for ix in 0 ..< ABMultiValueGetCount(numbers) {
let type = ABMultiValueCopyLabelAtIndex(numbers,ix).takeRetainedValue() as String
let number = ABMultiValueCopyValueAtIndex(numbers,ix).takeRetainedValue() as! String
let cleaned = self.removeSpecialCharsFromString(type)
let shortNumber = self.makeSpecialShortNumberFromString(number)
let phone = Number(number: number, short: shortNumber, type: cleaned)
personOfContact.addPhoneNumber(phone)
}
peapleOfContact.append(personOfContact)
}
}
return peapleOfContact
}
when xcode 7.1.1 is updated and used ios9, this library not work so used ContactUI Framework.
my code:
private func getContact(){
let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),
CNContactImageDataKey,
CNContactPhoneNumbersKey]
let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)
do {
try store.enumerateContactsWithFetchRequest(fetchRequest, usingBlock: { (let contact, let stop) -> Void in
self.contacts.append(contact)
})
}
catch let error as NSError {
print(error.localizedDescription)
}
}
and used like this:
self.getContact()
for contact in self.contacts{
print("Full name: \(CNContactFormatter.stringFromContact(contact, style: .FullName))")
print("Give name: \(contact.givenName)")
print("fimily name: \(contact.familyName)")
print("Idnetifier name: \(contact.identifier)")
for phoneNo in contact.phoneNumbers {
if phoneNo.label == CNLabelPhoneNumberMobile {
let number = (phoneNo.value as! CNPhoneNumber).stringValue
print("Phone Number: \(number)")
}
}
}
but not found contactId. How to get contactId ? How to use ContactUI Framework ?
advise me. thanks
In iOS 9.*, there is a new framework called 'Contacts'
Usage:
import Contacts
var validContacts: [CNContact] = []
let contactStore = CNContactStore()
// Request for contact access
contactStore.requestAccessForEntityType(.Contacts) { (granted, e) -> Void in
if granted {
do {
// Specify the key fields that you want to be fetched.
// Note: if you didn't specify your specific field request. your app will crash
let fetchRequest = CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey, CNContactMiddleNameKey, CNContactFamilyNameKey, CNContactEmailAddressesKey, CNContactPhoneNumbersKey, CNContactImageDataKey, CNContactThumbnailImageDataKey])
try contactStore.enumerateContactsWithFetchRequest(fetchRequest, usingBlock: { (contact, error) -> Void in
// Lets filter (optional)
if !contact.emailAddresses.isEmpty || !contact.phoneNumbers.isEmpty {
validContacts.append(contact)
}
})
print(validContacts)
}catch let e as NSError {
print(e)
}
}
}
Parsing:
// Loop through contatcs
for contact in validContacts {
var phoneNumbers: [String] = []
for phoneNumber in contact.phoneNumbers {
let value = phoneNumber.value as! CNPhoneNumber
phoneNumbers.append(value.stringValue)
}
var emailAddresses: [String] = []
for emailAddress in contact.emailAddresses {
let value = emailAddress.value as! String
emailAddresses.append(value)
}
if let imageData = contact.imageData {
let image = UIImage(data: imageData)
print("image: \(image)")
}
// Lets log
print("givenName: \(contact.givenName), middleName: \(contact.middleName), familyName: \(contact.familyName), phoneNumbers: \(phoneNumbers), emailAddresses: \(emailAddresses)\n")
}
I have a sample project which implement this.
GitHub
This code sample will help you :
public static func refreshContacts(){
let status = ABAddressBookGetAuthorizationStatus()
if status == .Denied || status == .Restricted {
// user previously denied, to tell them to fix that in settings
return
}
// open it
var error: Unmanaged<CFError>?
let addressBook: ABAddressBook? = ABAddressBookCreateWithOptions(nil, &error)?.takeRetainedValue()
if addressBook == nil {
println(error?.takeRetainedValue())
return
}
// request permission to use it
ABAddressBookRequestAccessWithCompletion(addressBook) {
granted, error in
if !granted {
// warn the user that because they just denied permission, this functionality won't work
// also let them know that they have to fix this in settings
return
}
if let people = ABAddressBookCopyArrayOfAllPeople(addressBook)?.takeRetainedValue() as? NSArray {
for person in people{
if let name = ABRecordCopyValue(person, kABPersonFirstNameProperty).takeRetainedValue() as? String {
println(name)//persons name
}
let numbers:ABMultiValue = ABRecordCopyValue(
person, kABPersonPhoneProperty).takeRetainedValue()
for ix in 0 ..< ABMultiValueGetCount(numbers) {
let label = ABMultiValueCopyLabelAtIndex(numbers,ix).takeRetainedValue() as String
let value = ABMultiValueCopyValueAtIndex(numbers,ix).takeRetainedValue() as! String
println("Phonenumber \(label) is \(value))
}
}
}
}
}
Please try this working for me. sort according to givenname(firstname). import Contacts first
let contactStore = CNContactStore()
var results: [CNContact] = []
do {
let request:CNContactFetchRequest
request = CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactMiddleNameKey, CNContactEmailAddressesKey,CNContactPhoneNumbersKey])
request.sortOrder = CNContactSortOrder.GivenName
try contactStore.enumerateContactsWithFetchRequest(request) {
(contact, cursor) -> Void in
results.append(contact)
}
}
catch{
print("Handle the error please")
}
print(results)

using public key encryption in swift

I am trying to use a public key provided to me by web service developer to securely transfer data. I have tried hard but I am not able to find any working example with latest swift version. I have coded it like following(with help from here:
func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge){
if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
var localTrust: UnsafeMutablePointer<SecTrust?>
let serverTrust = challenge.protectionSpace.serverTrust!
let serverPublicKey = SecTrustCopyPublicKey(serverTrust)
let certificateData = NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("pinning-certificate", ofType: "der")!)
let localCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, certificateData!)
let policy = SecPolicyCreateBasicX509()
if SecTrustCreateWithCertificates(localCertificate!, policy, localTrust) == errSecSuccess {
let localTrustRef = localTrust
let localPublicKey = SecTrustCopyPublicKey(localTrustRef)!
if (localPublicKey as AnyObject).isEqual(serverPublicKey as! AnyObject) {
print("trusted")
return challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
}
}
}
print("not trusted")
return challenge.sender!.cancelAuthenticationChallenge(challenge)
}
But I am getting following error during compilation in SecTrustCreateWithCertificates() and SecTrustCopyPublicKey():
Cannot convert value of type 'UnsafeMutablePointer?' to expected argument type 'UnsafeMutablePointer' (aka 'UnsafeMutablePointer>').
Edit 1: I have changed my code to following and now my code is executed but server is not receiving any request:
func extractIdentity(certData:NSData) -> IdentityAndTrust {
var identityAndTrust:IdentityAndTrust!
var securityError:OSStatus = errSecSuccess
let path: String = NSBundle.mainBundle().pathForResource("MobileAppClient", ofType: "pfx")!
let PKCS12Data = NSData(contentsOfFile:path)!
let key : NSString = kSecImportExportPassphrase as NSString
let options : NSDictionary = [key : "client"]
//create variable for holding security information
//var privateKeyRef: SecKeyRef? = nil
var items : CFArray?
securityError = SecPKCS12Import(PKCS12Data, options, &items)
if securityError == errSecSuccess {
let certItems:CFArray = items as CFArray!;
let certItemsArray:Array = certItems as Array
let dict:AnyObject? = certItemsArray.first;
if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {
// grab the identity
let identityPointer:AnyObject? = certEntry["identity"];
let secIdentityRef:SecIdentityRef = identityPointer as! SecIdentityRef!;
print("\(identityPointer) :::: \(secIdentityRef)")
// grab the trust
let trustPointer:AnyObject? = certEntry["trust"];
let trustRef:SecTrustRef = trustPointer as! SecTrustRef;
print("\(trustPointer) :::: \(trustRef)")
// grab the cert
let chainPointer:AnyObject? = certEntry["chain"];
identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: chainPointer! as! NSArray);
}
}
return identityAndTrust;
}
func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge){
if challenge.protectionSpace.authenticationMethod == (NSURLAuthenticationMethodServerTrust) {
let serverTrust:SecTrustRef = challenge.protectionSpace.serverTrust!
let certificate: SecCertificateRef = SecTrustGetCertificateAtIndex(serverTrust, 0)!
let remoteCertificateData = CFBridgingRetain(SecCertificateCopyData(certificate))!
let cerPath: String = NSBundle.mainBundle().pathForResource("Certificates", ofType: "cer")!
let localCertificateData = NSData(contentsOfFile:cerPath)!
challenge.sender?.useCredential(credential, forAuthenticationChallenge: challenge)
if (remoteCertificateData.isEqualToData(localCertificateData) == true) {
let credential:NSURLCredential = NSURLCredential(forTrust: serverTrust)
challenge.sender?.useCredential(credential, forAuthenticationChallenge: challenge)
} else {
SVProgressHUD.dismiss()
return challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
}
}
else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate
{
let path: String = NSBundle.mainBundle().pathForResource("Certificates", ofType: "p12")!
let PKCS12Data = NSData(contentsOfFile:path)!
let identityAndTrust:IdentityAndTrust = self.extractIdentity(PKCS12Data);
let urlCredential:NSURLCredential = NSURLCredential(
identity: identityAndTrust.identityRef,
certificates: identityAndTrust.certArray as? [AnyObject],
persistence: NSURLCredentialPersistence.ForSession);
challenge.sender?.useCredential(urlCredential, forAuthenticationChallenge: challenge)
}
}
Please find the answer given below:
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == (NSURLAuthenticationMethodServerTrust) {
let serverTrust:SecTrustRef = challenge.protectionSpace.serverTrust!
let certificate: SecCertificateRef = SecTrustGetCertificateAtIndex(serverTrust, 0)!
let remoteCertificateData = CFBridgingRetain(SecCertificateCopyData(certificate))!
let cerPath: String = NSBundle.mainBundle().pathForResource("xyz.com", ofType: "cer")!
let localCertificateData = NSData(contentsOfFile:cerPath)!
if (remoteCertificateData.isEqualToData(localCertificateData) == true) {
let credential:NSURLCredential = NSURLCredential(forTrust: serverTrust)
challenge.sender?.useCredential(credential, forAuthenticationChallenge: challenge)
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!))
} else {
completionHandler(NSURLSessionAuthChallengeDisposition.CancelAuthenticationChallenge, nil)
}
}
else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate
{
let path: String = NSBundle.mainBundle().pathForResource("client", ofType: "p12")!
let PKCS12Data = NSData(contentsOfFile:path)!
let identityAndTrust:IdentityAndTrust = self.extractIdentity(PKCS12Data);
let urlCredential:NSURLCredential = NSURLCredential(
identity: identityAndTrust.identityRef,
certificates: identityAndTrust.certArray as? [AnyObject],
persistence: NSURLCredentialPersistence.ForSession);
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, urlCredential);
}
else
{
completionHandler(NSURLSessionAuthChallengeDisposition.CancelAuthenticationChallenge, nil);
}
}
Add the following Code
struct IdentityAndTrust {
var identityRef:SecIdentityRef
var trust:SecTrustRef
var certArray:AnyObject
}
func extractIdentity(certData:NSData) -> IdentityAndTrust {
var identityAndTrust:IdentityAndTrust!
var securityError:OSStatus = errSecSuccess
let path: String = NSBundle.mainBundle().pathForResource("client", ofType: "p12")!
let PKCS12Data = NSData(contentsOfFile:path)!
let key : NSString = kSecImportExportPassphrase as NSString
let options : NSDictionary = [key : "xyz"]
//create variable for holding security information
//var privateKeyRef: SecKeyRef? = nil
var items : CFArray?
securityError = SecPKCS12Import(PKCS12Data, options, &items)
if securityError == errSecSuccess {
let certItems:CFArray = items as CFArray!;
let certItemsArray:Array = certItems as Array
let dict:AnyObject? = certItemsArray.first;
if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {
// grab the identity
let identityPointer:AnyObject? = certEntry["identity"];
let secIdentityRef:SecIdentityRef = identityPointer as! SecIdentityRef!;
print("\(identityPointer) :::: \(secIdentityRef)")
// grab the trust
let trustPointer:AnyObject? = certEntry["trust"];
let trustRef:SecTrustRef = trustPointer as! SecTrustRef;
print("\(trustPointer) :::: \(trustRef)")
// grab the cert
let chainPointer:AnyObject? = certEntry["chain"];
identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: chainPointer!);
}
}
return identityAndTrust;
}
I think that there are 2 problems:
1) To cast UnsafeMutablePointer you should call localTrust.memory but it will give you next error
2) Next error will give you that pointer in uninitialized, I think you can use code like this:
func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge){
if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
var localTrust: UnsafeMutablePointer<SecTrust?> = nil
let serverTrust = challenge.protectionSpace.serverTrust!
let serverPublicKey = SecTrustCopyPublicKey(serverTrust)
let certificateData = NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("pinning-certificate", ofType: "der")!)
let localCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, certificateData!)
let policy = SecPolicyCreateBasicX509()
if SecTrustCreateWithCertificates(localCertificate!, policy, localTrust) == errSecSuccess {
let localTrustRef = localTrust
let localPublicKey = SecTrustCopyPublicKey(localTrustRef.memory!)!
if (localPublicKey as AnyObject).isEqual(serverPublicKey as! AnyObject) {
print("trusted")
return challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
}
}
}
print("not trusted")
return challenge.sender!.cancelAuthenticationChallenge(challenge)
}
P.s. it's NOT safe to forcecast optional. Plese consider using if let statement

Resources