Z powodzeniem udało mi się wdrożyć TouchID z pękiem kluczy, a także udostępnianie pęków kluczy (synchronizacja elementów keychain między wieloma urządzeniami) oddzielnie. Kiedy próbuję zrobić oba, pojawia się błąd "-50", który jest nieprawidłowym parametrem. Z poniższego kodu usunięcie kSecAttrAccessControl lub kSecAttrSynchronizowalne działa zgodnie z oczekiwaniami.Czy w aplikacji na iOS można korzystać z uwierzytelniania dotykowego i udostępniania pęku kluczy?
Na podstawie mojego doświadczenia (czytaj - kilka dni frustracji) do tej pory, oraz w oparciu o możliwości jakiegoś Brelok API uproszczenia tools jak UICKeychainStore, wydaje się, że jeśli mogę użyć dotykowego uwierzytelniania tożsamości, brelok Udostępnianie wouldn” t działają i na odwrót. Szukam dokumentacji Apple, która by to określiła, ale nie mogła jej znaleźć.
Poszedłem przez Apple'a SecItem.h stronie, a useful info znalazłem stany następujące informacje kSecAttrAccessible i kSecAttrSynchronizable: „Jeśli oba atrybuty są podane na każdym OS X i iOS wartość dla kSecAttrAccessible klucz może być tylko jeden, którego nazwa nie kończy się „ThisDeviceOnly”, jako tych, którzy nie mogą synchronizować się z innym urządzeniem.”Jednakże, nie używam«ThisDeviceOnly»(obecnie używam kSecAttrAccessibleAlways w celach testowych)
Czy możesz pomóc w wskazaniu, czy i gdzie Apple to udokumentował ograniczenie? To pomogłoby mi udokumentować to dla rekordów i przejść dalej. Dzięki.
- (void)addKeychainItemWithIdentifier:(NSString *)identifier andData:(NSData *)data {
CFErrorRef error = NULL;
SecAccessControlRef sacObject;
sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleAlways,
kSecAccessControlUserPresence, &error);
if(sacObject == NULL || error != NULL)
{
NSString *msg0 = [NSString stringWithFormat:NSLocalizedString(@"SEC_ITEM_ADD_CAN_CREATE_OBJECT", nil), error];
[self printResultWithMessage:msg0];
return;
}
NSDictionary *attributes = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecValueData: data,
(__bridge id)kSecAttrAccessible:(__bridge id)kSecAttrAccessibleAlways,
(__bridge id)kSecAttrService: identifier,
(__bridge id)kSecAttrSynchronizable:(__bridge id)kCFBooleanTrue,
(__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacObject
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, nil);
NSError *statuserror = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil];
[self printResultWithMessage:[self keychainErrorToString:status]];
});
}
dobre pytanie! –