Hi,
I have created a new command line tool project, where I am trying to add a key to the keychain.
Error:
OSStatus: -34018
Error Description: A required entitlement isn't present.
Questions:
1. How can I resolve this error ? I am able to do the same thing using a mac app instead of a command line tool project.
2. Am I missing some key steps ?
Points to note:
- Signing: Automatically manage Signing
- Signing certificate - Development
main.swift
import Foundation
import CryptoKit
func storeKey(label: String) {
//Generate key
let key = P256.Signing.PrivateKey()
let attributes = [kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass: kSecAttrKeyClassPrivate] as [String: Any]
// Get a SecKey representation.
guard let secKey = SecKeyCreateWithData(key.x963Representation as CFData,
attributes as CFDictionary,
nil) else {
print("Unable to create SecKey representation.")
return
}
let query = [kSecClass: kSecClassKey,
kSecAttrApplicationLabel: label,
kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked,
kSecUseDataProtectionKeychain: true,
kSecValueRef: secKey] as [String: Any]
// Add the key to the keychain.
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else {
print("Unable to store item: \(status)")
print(SecCopyErrorMessageString(status, nil) ?? "")
return
}
print("successful")
}
storeKey(label: "TEST-KeyChain-Mac")
Attempts made:
1. Add Info.plist (contents shown below)
2. Add TestExample.entitlements (contents shown below)
After adding entitlements I get the following error:
Message from debugger: Error 1
Program ended with exit code: -1
Build Settings Changes:
CODE_SIGN_ENTITLEMENTS = TestExample/TestExample.entitlements
CODE_SIGN_INJECT_BASE_ENTITLEMENTS
INFOPLIST_FILE = TestExample/Info.plist
CREATE_INFOPLIST_SECTION_IN_BINARY = YES
PRODUCT_BUNDLE_IDENTIFIER = .TestExample
Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
</dict>
</plist>
TestExample.entitlements
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)<same reverse DNS>.TestExample</string>
</array>
</dict>
</plist>
If you want to use the iOS style keychain (which is what you’re doing when you specify
kSecUseDataProtectionKeychain
), you need a provisioning profile to whitelist your app identifier entitlement. macOS does not support this directly, so neither does Xcode. To make this work, you have to do something kludgy. See my
Packaging a Daemon with a Provisioning Profile post for details.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"