【问题标题】:Retrieve SecKey from NSData从 NSData 中检索 SecKey
【发布时间】:2016-06-29 11:08:15
【问题描述】:

我在 NSData 创建 SecKey 时遇到问题。基本上,我的客户端-服务器通信基于使用私钥创建的签名并使用公钥在服务器上进行验证。

我正在两个设备之间实现会话传输,为了继续通信,我还需要传输这些密钥。我正在将 SecKey 转换为 NSData 并通过蓝牙发送,但另一方面我无法将 NSData to SecKey 转换回使用加密。

你能帮忙吗?

【问题讨论】:

  • 你能粘贴你的代码吗?
  • @AmitKalghatgi 你想要哪一部分?我有接收“NSData”的功能?并且应该返回 SecKey(或 SecKeyRef)

标签: ios swift bluetooth seckeyref


【解决方案1】:

更完整的示例(swift 4,iOS 10+) - 假设您有一个 Base64 编码的字符串。请注意,连接的另一端也需要使用相同的格式创建密钥有效负载(即 RSA - PKCS #1,也验证密钥大小)。此函数处理公钥或私钥(为简洁起见,省略了安全警告)。

// Extract secKey from encoded string - defaults to extracting public keys
func decodeSecKeyFromBase64(encodedKey: String, isPrivate: Bool = false) -> SecKey? {
    var keyClass = kSecAttrKeyClassPublic
    if isPrivate {
        keyClass = kSecAttrKeyClassPrivate
    }
    let attributes: [String:Any] =
    [
        kSecAttrKeyClass as String: keyClass,
        kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
        kSecAttrKeySizeInBits as String: 2048,
    ]

    guard let secKeyData = Data.init(base64Encoded: encodedKey) else {
        print("Error: invalid encodedKey, cannot extract data")
        return nil
    }
    guard let secKey = SecKeyCreateWithData(secKeyData as CFData, attributes as CFDictionary, nil) else {
        print("Error: Problem in SecKeyCreateWithData()")
        return nil
    }

    return secKey
}

【讨论】:

    【解决方案2】:

    iOS 10开始可以使用以下代码:

    let attributes: [String:Any] = [
                kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
                kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
                kSecAttrKeySizeInBits as String: blockSize,
                ]
    secKey = SecKeyCreateWithData(secKeyData as CFData, attributes as CFDictionary, nil)
    

    【讨论】:

      【解决方案3】:

      我成功使用的东西......

      func obtainKeyData(tag: String) -> NSData? {
          var keyRef: AnyObject?
          let query: Dictionary<String, AnyObject> = [
              String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
              String(kSecReturnData): kCFBooleanTrue as CFBoolean,
              String(kSecClass): kSecClassKey as CFStringRef,
              String(kSecAttrApplicationTag): tag as CFStringRef,
              ]
      
          let result: NSData?
      
          switch SecItemCopyMatching(query, &keyRef) {
          case noErr:
              result = keyRef as? NSData
          default:
              result = nil
          }
      
          return result
      }
      
      func insertPublicKey(publicTag: String, data: NSData) -> SecKeyRef? {
          let query: Dictionary<String, AnyObject> = [
              String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
              String(kSecClass): kSecClassKey as CFStringRef,
              String(kSecAttrApplicationTag): publicTag as CFStringRef,
              String(kSecValueData): data as CFDataRef,
              String(kSecReturnPersistentRef): true as CFBooleanRef]
      
          var persistentRef: AnyObject?
          let status = SecItemAdd(query, &persistentRef)
      
          if status != noErr && status != errSecDuplicateItem {
              return nil
          }
      
          return obtainKey(publicTag)
      }
      func obtainKey(tag: String) -> SecKey? {
          var keyRef: AnyObject?
          let query: Dictionary<String, AnyObject> = [
              String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
              String(kSecReturnRef): kCFBooleanTrue as CFBoolean,
              String(kSecClass): kSecClassKey as CFStringRef,
              String(kSecAttrApplicationTag): tag as CFStringRef,
              ]
      
          let status = SecItemCopyMatching(query, &keyRef)
      
          switch status {
          case noErr:
              if let ref = keyRef {
                  return (ref as! SecKeyRef)
              }
          default:
              break
          }
      
          return nil
      }
      

      没有简单的方法来传输密钥对的私有部分(有可能,但尽量避免)

      【讨论】:

      • 是的,我也有这部分代码,但是这里的问题是它严格绑定到标签,可能是自动生成的。
      • 我可以对私钥标签做同样的事情吗?还是我需要用不同的方式来做?
      • 不,使用私钥无法使用。原因是,私钥应该是私有的,因此通常不容易转移到其他设备。首先尝试更改您的程序流程。
      • @Array .. 更具体地说,SecItemAdd 将因私钥失败...(iOS)
      猜你喜欢
      • 2017-06-03
      • 1970-01-01
      • 1970-01-01
      • 2013-04-04
      • 2020-08-09
      • 2014-09-13
      • 1970-01-01
      • 2015-12-25
      • 1970-01-01
      相关资源
      最近更新 更多