Swift钥匙串不会加载外部生成的密钥。加载密钥后,SecKey返回Nil值,没有错误

时间:2019-12-24 13:31:21

标签: ios swift keychain

我是SWIFT,iOS和密码学的新手。请多多包涵。我无法在Swift 5的iOS钥匙串中加载外部密钥。我在Stackoverflow和其他网站上遇到了几篇关于将密钥加载到iOS钥匙串中的困难的文章。

我的目标是使用端口22,公共密钥和用户名凭据建立到远程SFTP服务器的SSH连接。截至目前,防火墙规则允许使用NMSSH(来自GIT)连接到服务器,但是如果在iphone和Windows服务器之间不交换公钥,我将无法进行身份验证。我多次从Swift项目中生成密钥对,并将公钥发送给Windows服务器管理员,以将其添加到SSH设置中的用户名中。管理员的所有尝试均因服务器锁定而失败。因此,最后他使用puTTYGen在服务器中生成了一个密钥对,将公钥添加到我的用户名中,并将该密钥对发送给我以添加到iOS钥匙串中。

我先将私钥导出到puTTYgen中的OpenSSL,然后将其转换为base64编码的字符串,然后再在GIT(https://github.com/btnguyen2k/swiftutils)的RSAUtils中使用它。该过程有效,但将SecKey返回为Nil。看起来钥匙从未进入钥匙扣。

在使用此GIT代码之前,我尝试过几次使用secItemAdd。该代码的工作原理和显示方式类似于获取密钥,但在SecItemCopyMatching中返回Nil作为SecKey值。

我还冒险通过在http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/中创建.h标头,.m文件和.m代码的桥来在Swift中添加Objective-C。同样的问题。上面的.m完成后,我得到一个Nil并返回一个值。

我正在处理的私钥具有页眉和页脚----- BEGIN RSA PRIVATE KEY -----和----- END RSA PRIVATE KEY -----。我可以在键中看到类似+,/等字符,提示它不是base64,所以我使用String扩展名将其转换。

func toBase64() -> String {
    return Data(self.utf8).base64EncodedString()

代码:


// 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)")
    }

}

我的目标是将密钥从外部加载到iOS钥匙串。我还尝试发送通过使用https://digitalleaves.com/blog/2015/10/sharing-public-keys-between-ios-and-the-rest-of-the-world/中建议的CryptoExportImportManager()创建的公共密钥。就像我之前说过的那样,我的Windows服务器管理员在尝试加载此类密钥时报告服务器锁定。

感谢您的帮助。 谢谢

1 个答案:

答案 0 :(得分:0)

我正在用自己的答案对此进行更新。在尝试了上述链接(Digital Leaf和Flirble.org)中提到的两个解决方案几周后,我可以使用I-phone 7上的NMSSH连接到Windows服务器并对其进行身份验证。我无法使用I-phone钥匙串进行存储外部生成的密钥。太乏味了。我能找到的最好的办法是在钥匙串中添加一个私钥,但是当我尝试检索它时,它总是返回Nil。

我遵循了NMSSH建议的连接步骤,使用了cocopod,将其添加到框架中并添加了库。在使用NMSSH会话类时,我使用了in memory keys选项中的方法。重要的是将公用密钥参数保留为空白,并提供专用密钥和专用密钥的密码。