Reputation: 81
I am new to SWIFT, iOS as and Cryptography. Please bear with me. I am unable to load external keys in the iOS keychain in Swift 5. I came across several posts in Stackoverflow and other sites about the difficulty in loading keys into an iOS keychain.
My goal is to establish an SSH connection to a remote SFTP server using port 22, the public key and user name credentials. As of now, a firewall rule allows connection to the server using NMSSH (from GIT), but I am unable to authenticate without public keys exchanged between i-phone and Windows server. I generated key pairs from my Swift project several times and sent public key to Windows server admin to add it to my user name in SSH setup. All attempts by the admin failed with server lockouts. So finally he generated a key pair in the server using puTTYGen, added the public key to my user name and sent the key pair to me to add to an iOS keychain.
I exported the private key to OpenSSL in puTTYgen and converted it to base64 encoded string before using it in RSAUtils in GIT (https://github.com/btnguyen2k/swiftutils). The process works but returns SecKey as Nil. Looks like the key never made it to the keychain.
Before using this GIT code, I tried several times to use secItemAdd. The code works and shows like taking the key, but returns Nil as SecKey value in SecItemCopyMatching.
I also ventured into adding Objective-C in Swift by creating a .h header, a .m file and a bridge for the .m code in http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/. Same issue. I get a Nil after the above .m completes and returns a value.
The private key I am dealing with has header and footer -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY-----. I can see characters like +, / etc in the key suggesting that it is not base64, so I used a String extension to convert it.
func toBase64() -> String {
return Data(self.utf8).base64EncodedString()
The code:
// added to use GIT code
// https://github.com/btnguyen2k/swiftutils.git
// variable declared at class level
var pKeyContents: String = ""
func addKeys2() {
let tag: String = "com.mail.private"
// if let path = Bundle.main.path(forResource: "PKeyWOHeader", ofType: "txt") // I tried this first after manually removing header and footer ("BEGIN ....KEY AND "END ... KEY" etc). It didn't work
if let path = Bundle.main.path(forResource: "ExportAsOpenSSL", ofType: "") // This one is a dump of puTTYgen export to openssl of private key
{
do {
let contents = try String(contentsOfFile: path)
pKeyContents = contents
}
catch {
print("Contents could not be loaded")
return
}
} else {
print("File not found")
return
}
let myData = pKeyContents.data(using: String.Encoding.utf8)
let encoded = pKeyContents.toBase64()
//let instanceOfObjCKeyFix = ObjCKeyFix()
//privateKeyAsData = instanceOfObjCKeyFix.stripPublicKeyHeader(myData)
// stringFromData = String(decoding: privateKeyAsData!, as: UTF8.self)
// Above lines were an attempt to use Objective C code from
// http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/.
// This was also returning nil value
do {
try privateKey = RSAUtils.addRSAPrivateKey(encoded, tagName: tag)
print(privateKey as Any) // returns nil
} catch {
print("error)")
}
}
My goal is to load keys from outside to iOS keychain. I also tried sending public key created by using CryptoExportImportManager() suggested in https://digitalleaves.com/blog/2015/10/sharing-public-keys-between-ios-and-the-rest-of-the-world/. Like I said before, my Windows server admin reports server locks while attempting to load such keys.
Any help is appreciated. Thanks
Upvotes: 0
Views: 457
Reputation: 81
I am updating this with my own answer. After several weeks of trying two solutions referred in above links (Digital Leaves and Flirble.org), I could get connected and authenticated to a Windows server using NMSSH from an I-phone 7. I couldn't use I-phone keychain to store externally generated keys. It was too tedious. The best I could get to was add a private key to keychain, but it always returned Nil when I tried to retrieve it.
I followed connection steps recommended in NMSSH, used cocopod, added to framework and added libraries. While using NMSSH sessions class, I used the method with in memory keys option. The important point is to leave public key parameter blank and provide private key and password for private key.
Upvotes: 0