SecKeyCopyKeyExchangeResult不能在iOS 13中用作Node.js ecdh

时间:2019-10-02 10:28:08

标签: ios swift

我有一个应用程序,使用secp521r1曲线上的ECDH在iOS / android / nodejs之间生成共享秘密。为了确保它能正常工作,我编写了一个测试,该测试使用由nodejs生成的数据,并且一直运行到iOS 13。

测试的源代码为:

let publicKey = "BABBvZ56c4bj1Zo73LIt/bBVa3jvGTA1fceoOG/M9TeXHx5ffCggRteEVS+bwrgQWPOwJPHhevNenaVn32ZnhztS0QFBqKGZTF1pKNSvuj+PDKQ625TauNroq+LQdeS+Pn6GVHL0iW5pp84NZ06L97VZ9HYm+g2lMnlUFV8hco2CmwBqHQ=="
let privateKey = "AXn994UN59QCEqmCmXmmNZ3hVZPlMwzTIeBupJGG4CqDWfWLuCTui7qiBfQtCFcQ1ks4NNB/tHEZUJ+bB97+pkJ3"
let otherBase64 = "BAAzWyzdh2e+ZNUCFt4oDADURb8+m9WA7gbWtTo57ZP3U23VuvMnRHf+12GpTSV8A5pt+vZfaR2cT02P+LPRc/kGzgAT2IYIgDz/cKbzMi520ZLa0GYk1xzCuNqFhdBZmrB5w0ymsPLdJzIG1QZ3xu7OufEipm5D41abphLLnbH+OyTX6w=="
let expectedShared = "AQkTOOHPcvlXufR2dm1FHaIJRlTgmxTJMI+h0kJ+nMVNopIP+opSqUNmflsgnJzT8JTodd/eehaaq5vvYdDVciIQ"

// iOS secKey is reconstructed by concatenating public and private key
let otherDataKey = Data.init(base64Encoded: otherBase64)!
var concatenatedKey = Data.init(base64Encoded: publicKey)!
concatenatedKey.append(Data.init(base64Encoded: privateKey)!)

// generate private key
var attributes: [String:Any] =
  [
    kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
    kSecAttrKeySizeInBits as String:      521,
    kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
]
var error: Unmanaged<CFError>?
guard let secKey = SecKeyCreateWithData(concatenatedKey as CFData, attributes as CFDictionary, &error) else {
  XCTAssertTrue(false)
  return
}

// generate other public key
attributes[kSecAttrKeyClass as String] = kSecAttrKeyClassPublic
guard let otherKey = SecKeyCreateWithData(otherDataKey as CFData, attributes as CFDictionary, nil) else {
  XCTAssertTrue(false)
  return
}

// generate shared secret
let exchangeOptions: [String: Any] = [:]
guard let shared = SecKeyCopyKeyExchangeResult(secKey, SecKeyAlgorithm.ecdhKeyExchangeStandardX963SHA256, otherKey, exchangeOptions as CFDictionary, &error) else {
  XCTAssertTrue(false)
  return
}

// generate shared secret
XCTAssertEqual((shared as Data).base64EncodedString(), expectedShared);

在iOS 13上,我被迫按照此处讨论的方法修改我的exchangeOptions词典的内容(SecKeyCopyKeyExchangeResult() function return an error, "kSecKeyKeyExchangeParameterRequestedSize is missing"

let exchangeOptions: [String: Any] = [SecKeyKeyExchangeParameter.requestedSize.rawValue as String: 66]

问题在于,使用此选项,SecKeyCopyKeyExchangeResult的结果与nodejs one不再匹配(在iOS 12上也是如此)

1 个答案:

答案 0 :(得分:1)

我终于找到了解决方案...在iOS <= 12中,尝试使用ecdhKeyExchangeStandardX963SHA256算法时,交换参数留为空白,这又回到了使用SecKeyAlgorithm.ecdhKeyExchangeCofactor。

因此,重现先前行为的修补程序是使用

修改SecKeyCopyKeyExchangeResult
// generate shared secret
let exchangeOptions: [String: Any] = [:]
guard let shared = SecKeyCopyKeyExchangeResult(secKey, SecKeyAlgorithm.ecdhKeyExchangeCofactor, otherKey, exchangeOptions as CFDictionary, &error) else {
  XCTAssertTrue(false)
  return
}

这至少适用于iOS 10至13