我需要使用推送通知服务扩展共享主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 }
}
到目前为止这不起作用......