从NSData中检索SecKey



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

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

请你帮忙好吗?

更完整的例子(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
}

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)

我成功的秘诀是……

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
}

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

最新更新