swift 2.0 keychain type errors for SecItemCopyMatching
It seems, we don't need Unmanaged<>
work anymore.
Try:
var retrievedData: NSData?
var extractedData: AnyObject?
let status = SecItemCopyMatching(keyChainQuery, &extractedData)
if (status == errSecSuccess) {
retrievedData = extractedData as? NSData
}
SecItemCopyMatching always returns 'does not appear to be a valid keychain item' for a stored EC key
You made a minor mistake at kSecClass as String : kSecAttrKeyType
. kSecAttrKeyType
is a key indicating the type of the key (kSecAttrKeyTypeEC
/kSecAttrKeyTypeECSECPrimeRandom
/kSecAttrKeyTypeRSA
). So you should pass the correct kSecClass
which for you should be kSecClassKey
.
I'd like to point out that the output of the SecCopyErrorMessageString
is a bit bad every now and then. Always try to print the OSStatus
as well and use that on OSStatus. Which in this case would not have given you greatest hits, as it would've returned -50. But the combination of the two identifies them uniquely enough to define it as errSecNoSuchClass
found here.
How to call SecItemCopyMatching in Xcode 7 beta 4?
This works on Xcode 7 beta 4
var dataTypeRef: AnyObject?
let status: OSStatus = withUnsafeMutablePointer(&dataTypeRef) { SecItemCopyMatching(keychainQuery as CFDictionaryRef, UnsafeMutablePointer($0)) }
if status == noErr {
return dataTypeRef as? NSData
}
else {
return nil
}
Generate keychain key with swift 2.0
Try:
public func generateKeyPair(publicKeyTag: String, privateKeyTag:String, keySize: Int) -> KeyPair? {
let privateKeyAttr: [NSString: AnyObject] = [
kSecAttrIsPermanent: true,
kSecAttrApplicationTag: privateKeyTag
]
let publicKeyAttr: [NSString: AnyObject] = [
kSecAttrIsPermanent: true,
kSecAttrApplicationTag: publicKeyTag
]
let parameters: [NSString: AnyObject] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits: keySize,
kSecPrivateKeyAttrs: privateKeyAttr,
kSecPublicKeyAttrs: publicKeyAttr
]
var publicKey: SecKey?
var privateKey: SecKey?
let result = SecKeyGeneratePair(parameters, &publicKey, &privateKey)
if result != errSecSuccess {
return nil
}
return KeyPair(publicKey: publicKey!, privateKey: privateKey!)
}
You can pass in-out &
expressions to UnsafeMutablePointer
parameters.
See also: swift 2.0 keychain type errors for SecItemCopyMatching
Using SecKeychainCreate from Swift
The promptUser
parameter of SecKeychainCreate()
has the type Boolean
, which is a "Mac OS historic type" and an alias to UInt8
,
so it is different from the Swift Bool
in Swift 1.2.
(Compare Type 'Boolean' does not conform to protocol 'BooleanType' for a similar issue.)
This means that you have to
pass Boolean(0)
instead of false
:
SecKeychainCreate(pathName, UInt32(0), nil, Boolean(0), nil, pointer)
Additional remarks:
withUnsafeMutablePointer()
is not needed, you can pass&keychain
to the keychain functions.(path as NSString).UTF8String
is not needed, you can pass a Swift
string to a C function expecting aconst char *
parameter,
compare String value to UnsafePointer<UInt8> function parameter behavior.- Passing
nil
as password toSecKeychainCreate()
is only allowed
ifpromptUser
isTRUE
, otherwise it causes a
"parameter error (-50)". SecKeychainOpen()
succeeds even if the keychain file does not
exists. According to the documentation, you have to checkSecKeychainGetStatus()
. Alternatively, you can try to create
the keychain file first, as for example in Open Local Items Keychain?.
Together:
let path = "/path/to/my.keychain"
var keychain: Unmanaged<SecKeychain>?
var status = SecKeychainCreate(path, 0, "", Boolean(0), nil, &keychain)
if status == OSStatus(errSecDuplicateKeychain) {
status = SecKeychainOpen(path, &keychain)
}
As of Swift 2 / Xcode 7 beta 5, the Mac type Boolean
is mapped
to Swift as Bool
, and the key chain functions do no longer return
unmanaged objects:
let path = "/path/to/my.keychain"
var keychain: SecKeychain?
var status = SecKeychainCreate(path, 0, "", false, nil, &keychain)
if status == OSStatus(errSecDuplicateKeychain) {
status = SecKeychainOpen(path, &keychain)
}
function error handling in Swift 2
InSwift 2 error handling has changed from NSError
in-out parameters to try/catch (not exceptions).
I think this is a correct conversion from NSError
to try/catch:
func focusWithMode(focusMode:AVCaptureFocusMode, exposureMode:AVCaptureExposureMode, point:CGPoint, monitorSubjectAreaChange:Bool){
dispatch_async(self.sessionQueue!, {
var device: AVCaptureDevice! = self.videoDeviceInput!.device
var error: NSError? = nil
do {
try device.lockForConfiguration()
if device.focusPointOfInterestSupported && device.isFocusModeSupported(focusMode){
device.focusMode = focusMode
device.focusPointOfInterest = point
}
if device.exposurePointOfInterestSupported && device.isExposureModeSupported(exposureMode){
device.exposurePointOfInterest = point
device.exposureMode = exposureMode
}
device.subjectAreaChangeMonitoringEnabled = monitorSubjectAreaChange
device.unlockForConfiguration()
}
catch {
print("Locked error!")
}
})
}
Related Topics
Map and Flatmap Difference in Optional Unwrapping in Swift 1.2
How to Implement iOS 11's Mkusertrackingbutton
Swift Can't Infer Generic Type When Generic Type Is Being Passed Through a Parameter
Redeclaring Members in an Extension Hides the Original Member *Sometimes*. Why
Missing Argument for Parameter 'From' in Call When Creating Instance of Codable Class
Generatesdecimalnumbers for Numberformatter Does Not Work
Why Does Swift Not Allow Stored Properties in Extensions
How to Handle Two Different Types in an Array in Swift for a Uitableview
Disable Scrolling in Swiftui List/Form
Why Does Realitykit Memory Does Not Clear After Deinit Called
Swift, Sprite Kit Game: Have Circle Disappear in Clockwise Manner? on Timer
System Volume Change Observer Not Working on iOS 15
Waiting for Alamofire in Unit Tests
Swift & Firebase - How to Store More User Data Other Than Email and Password