Posts

Post not yet marked as solved
1 Replies
2.3k Views
We are developing an i-phone app in Swift 5 that needs a SSH connection to a remote Windows server. Every night, data collected in SQLite database should be pushed to the Windows server. The approved authentication method is to use SSH server URL in port 22 and my user ID.With a new firewall rule, I am able to connect using URL, port 22 and my user name, but I am not authenticated. From this point on, I need public keys exchanged and added at both ends. Obviouly, data encrption will need to be done using public keys and dedcryption with private keys.I need to accomplish two tasks:1. Create a keypair in iOS and send the public key to Windows Admin to add my user ID.2. Add a public key sent by server admin to iOS keychain in my app for later use in data encryption1. Creation of keypair in Swift 5I used SecKeyGeneratePair to create key pair.Code: func createKeys1() { var statusCode: OSStatus? var publicKey: SecKey? var privateKey: SecKey? var error: Unmanaged<CFError>? let publicKeyAttr: [NSObject: NSObject] = [ kSecAttrIsPermanent:true as NSObject, kSecAttrApplicationTag:"com.mycompany.mailtracking1.public".data(using: String.Encoding.utf8)! as NSObject, kSecClass: kSecClassKey, kSecReturnData: kCFBooleanTrue] let privateKeyAttr: [NSObject: NSObject] = [ kSecAttrIsPermanent:true as NSObject, kSecAttrApplicationTag:"com.mycompany.mailtracking1.private".data(using: String.Encoding.utf8)! as NSObject, kSecClass: kSecClassKey, kSecReturnData: kCFBooleanTrue] var keyPairAttr = [NSObject: NSObject]() keyPairAttr[kSecAttrKeyType] = kSecAttrKeyTypeRSA keyPairAttr[kSecAttrKeySizeInBits] = 2048 as NSObject keyPairAttr[kSecPublicKeyAttrs] = publicKeyAttr as NSObject keyPairAttr[kSecPrivateKeyAttrs] = privateKeyAttr as NSObject statusCode = SecKeyGeneratePair(keyPairAttr as CFDictionary, &publicKey, &privateKey) if statusCode == noErr && publicKey != nil && privateKey != nil { print("Key pair generated OK") }// I read that the key should be converted to base64 encoded format for external use, so the code below was added // Generate exportable public key let publicKeyData = SecKeyCopyExternalRepresentation(publicKey!, &error)// The above public key was sent to Windows server admin but he couldn't load it in server against my user name. He reported server locks and errors with multiple tries.2. Add key sent by server admin to iOS keychainvar pKeyContents: String = ""var publicKey: SecKey?var privateKey: SecKey?var privateKeyAsData: Data?var stringFromData: String = ""func addKeys1() { // convert private key to PKCS#8 format // This command worked in terminal // openssl pkcs8 -topk8 -in yixtest.goldlnk.rootlnka.net.key -out yixtest.goldlnk.rootlnka.net.keypkcs8.key // It will prompt to enter PW twice // -nocrypt was removed since it kept giving errors // Refer stackoverflow search secitemadd-keep-return-50-error-in-swift // secItemAdd keep return -50 error in swift // The code below is to add a test key (a private key) // I removed "BEGIN.....KEY" and "END ... KEY" manually to file "PkeyWOHeader" and added it to project bundle if let path = Bundle.main.path(forResource: "PKeyWOHeader", ofType: "txt") { do { let contents = try String(contentsOfFile: path) print("Printing Contents -- \(contents)") pKeyContents = contents } catch { print("Contents could not be loaded") return } } else { print("File not found") return } // Now add the key to keychain print("Start adding key") let key: Data = pKeyContents.data(using: .utf8)! let tag: Data = "com.mycompany.mailtracking2.private".data(using: .utf8)! let addQuery: [String: Any] = [kSecClass as String: kSecClassKey, kSecAttrApplicationTag as String: tag, kSecValueData as String: key] var result: CFTypeRef? = nil let status = SecItemAdd(addQuery as CFDictionary, &result) if status == errSecSuccess { print("Key successfully added") } else { if let error: String = SecCopyErrorMessageString(status, nil) as String? { print(error) print("Error adding key") } return } }I have been trying secItemAdd to add the Windows server key without success. secItemAdd completes without errors, but returns secKey as Nil. It appears, from several research in internet, that the iOS keychain has very unique requirements and is different from several other applications that use OpenSSL to do these kinds of things in minutes.Site below suggests that keys generated in iOS is not in ASCII and needs a base64 decoder. In addition uses PKCS# 1 but is missing ASN1 preambles. So, accepting an external key would mean removing these preambles. Being new to iOS in general and cryptography in particular, I am not sure what this meant. I just added the Objective C code in Swift with a header bridge, etc. I still get a nil value for SecKey outputhttp://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/The site below suggested using a GITHUB utility called CryptoExportImportManager(), but that also didn't helphttps://digitalleaves.com/blog/2015/10/sharing-public-keys-between-ios-and-the-rest-of-the-world/If I were in Apple support, I would have ignored these third party solutions as "not supported". I get that. But, I am trying find a way to fix above two issues.Any help is appreciatedDharma
Posted
by DharmaV.
Last updated
.