我需要与推送通知服务扩展共享主iOS应用程序生成的私钥 . 使用SecItemCopyMatching()获取密钥在应用程序中正常工作 . 但是,如果我尝试从服务扩展中获取私钥,我会得到一个“errSecItemNotFound” .

这是我正在做的事情:

在主应用程序中,我生成一个密钥对,并使用SecItemAdd()将其存储在钥匙串中 . 生成密钥对时,我不使用“kSecAttrIsPermanent:true”属性,因为它不允许指定“kSecAttrAccessGroup” . 据我所知,钥匙串共享我需要指定一个访问组来在应用程序之间或扩展程序和应用程序之间共享密钥 .

kSecAttrAccessGroup是我指定的字符串,它看起来像这样:"MyAppIdentifierPrefix" "com.example.app.my-keychain" keyTag也是我指定的字符串,如下所示:"com.example.app.my-key"

// private key parameters
    let privateKeyParams: [String: AnyObject] = [
        kSecAttrApplicationTag as String: keyTag as AnyObject
    ]

    // public key parameters
    let publicKeyParams: [String: AnyObject] = [
        kSecAttrApplicationTag as String: keyTag as AnyObject
    ]

    // global parameters for key generation
    let parameters: [String: AnyObject] = [
        kSecAttrKeyType as String:          myKeyType,
        kSecAttrKeySizeInBits as String:    myKeySize as AnyObject,
        kSecPublicKeyAttrs as String:       publicKeyParams as AnyObject,
        kSecPrivateKeyAttrs as String:      privateKeyParams as AnyObject
    ]

    // generate the key pair
    var pubKey, privKey: SecKey?
    let status = SecKeyGeneratePair(parameters as CFDictionary, &pubKey, &privKey)

    if status == errSecSuccess {
        // parameters for public key
        let pubKeyParameters: [String: AnyObject] = [
            kSecClass as String: kSecClassKey,
            kSecAttrAccessible as String: kSecAttrAccessibleAlways,
            kSecAttrAccessGroup as String: keychainGroupName as AnyObject,
            kSecAttrIsPermanent as String: true as AnyObject,
            kSecAttrApplicationTag as String: keyTag as AnyObject,
            kSecAttrKeyType as String: myKeyType,
            kSecAttrKeySizeInBits as String: myKeySize as AnyObject,
            kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
            kSecValueRef as String: pubKey!
        ]
        // add public key to keychain
        let statusPubKey = SecItemAdd(pubKeyParameters as CFDictionary, nil)

        // parameters for private key
        let privKeyParameters: [String: AnyObject] = [
            kSecClass as String: kSecClassKey,
            kSecAttrAccessible as String: kSecAttrAccessibleAlways,
            kSecAttrAccessGroup as String: keychainGroupName as AnyObject,
            kSecAttrIsPermanent as String: true as AnyObject,
            kSecAttrApplicationTag as String: keyTag as AnyObject,
            kSecAttrKeyType as String: myKeyType,
            kSecAttrKeySizeInBits as String: myKeySize as AnyObject,
            kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
            kSecValueRef as String: privKey!
        ]
        // add private key to keychain
        let statusPrivKey = SecItemAdd(privKeyParameters as CFDictionary, nil)
    }

我在功能选项卡中启用了钥匙串共享,并为应用程序和推送通知服务扩展指定了相同的标识符"com.example.app.my-keychain" .

获取密钥字节的函数如下:

func getPrivateKeyData(keyTag: String) -> Data? {
    let parameters = [
        kSecClass as String: kSecClassKey,
        kSecAttrApplicationTag as String: keyTag,
        kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
        kSecAttrAccessGroup as String: keychainGroupName as AnyObject,
        kSecReturnData as String: true
        ] as [String : Any]
    var data: AnyObject?
    let status = SecItemCopyMatching(parameters as CFDictionary, &data)
    if status == errSecSuccess {
        return data as? Data
    } else { return nil }
}

到目前为止,这不起作用......