Moje pytanie dotyczy pęków kluczy w iOS (iPhone, iPad, ...). Myślę (ale nie jestem pewien), że implementacja pęków kluczy pod Mac OS X rodzi to samo pytanie z tą samą odpowiedzią.
iOS udostępnia pięć typów (klas) elementów pęku kluczy. Aby kSecClass
określić typ, musisz wybrać jedną z tych pięciu wartości dla klucza :
kSecClassGenericPassword used to store a generic password
kSecClassInternetPassword used to store an internet password
kSecClassCertificate used to store a certificate
kSecClassKey used to store a kryptographic key
kSecClassIdentity used to store an identity (certificate + private key)
Po długim czasie czytania dokumentacji jabłka, blogi i wpisy w forum, dowiedziałem się, że pozycja brelok typu kSecClassGenericPassword
dostaje swoją wyjątkowość z atrybutami kSecAttrAccessGroup
, kSecAttrAccount
a kSecAttrService
.
Jeśli te trzy atrybuty w żądaniu 1 są takie same jak w żądaniu 2, otrzymasz ten sam ogólny element pęku kluczy haseł, niezależnie od innych atrybutów. Jeśli jeden (lub dwa lub wszystkie) z tych atrybutów zmieni swoją wartość, otrzymasz różne przedmioty.
Ale kSecAttrService
jest dostępny tylko dla elementów typu kSecClassGenericPassword
, więc nie może być częścią „unikalnego klucza” przedmiotu innego typu i wydaje się, że nie ma dokumentacji, która jasno wskazywałaby, które atrybuty jednoznacznie określają przedmiot pęku kluczy.
Przykładowy kod w klasie „KeychainItemWrapper” elementu „GenericKeychain” używa tego atrybutu, kSecAttrGeneric
aby uczynić element unikalnym, ale jest to błąd. Tylko dwa wpisy w tym przykładzie są przechowywane jako dwa odrębne wpisy, ponieważ kSecAttrAccessGroup
są różne (jeden ma ustawioną grupę dostępu, a drugi umożliwia zwolnienie). Jeśli spróbujesz dodać drugie hasło bez grupy dostępu, używając Apple KeychainItemWrapper
, nie powiedzie się.
Więc proszę, odpowiedz na moje pytania:
- Czy to prawda, że połączenie
kSecAttrAccessGroup
,kSecAttrAccount
ikSecAttrService
jest „unikalny klucz” z pęku kluczy elementu, którego kSecClass jestkSecClassGenericPassword
? - Jakie atrybuty sprawiają, że przedmiot pęku kluczy jest wyjątkowy, jeśli
kSecClass
nie jestkSecClassGenericPassword
?
źródło
Odpowiedzi:
Klucze podstawowe są następujące (pochodzące z plików open source firmy Apple, zobacz Schema.m4 , KeySchema.m4 i SecItem.cpp ):
kSecClassGenericPassword
kluczem podstawowym jest kombinacjakSecAttrAccount
ikSecAttrService
.kSecClassInternetPassword
, klucz podstawowy jest kombinacjąkSecAttrAccount
,kSecAttrSecurityDomain
,kSecAttrServer
,kSecAttrProtocol
,kSecAttrAuthenticationType
,kSecAttrPort
ikSecAttrPath
.kSecClassCertificate
, klucz podstawowy jest kombinacjąkSecAttrCertificateType
,kSecAttrIssuer
ikSecAttrSerialNumber
.kSecClassKey
, klucz podstawowy jest kombinacjąkSecAttrApplicationLabel
,kSecAttrApplicationTag
,kSecAttrKeyType
,kSecAttrKeySizeInBits
,kSecAttrEffectiveKeySize
, i twórca, datę rozpoczęcia i zakończenia, które nie są narażone przez SecItem jeszcze.kSecClassIdentity
nie znalazłem informacji o polach klucza podstawowego w plikach typu open source, ale ponieważ tożsamość jest połączeniem klucza prywatnego i certyfikatu, zakładam, że klucz podstawowy to kombinacja klucza podstawowego pola dlakSecClassKey
ikSecClassCertificate
.Ponieważ każdy element pęku kluczy należy do grupy dostępu do pęku kluczy, wydaje się, że grupa dostępu do pęku kluczy (pole
kSecAttrAccessGroup
) jest polem dodanym do wszystkich tych kluczy podstawowych.źródło
kSecClass
siękSecClassCertificate
lubkSecClassKey
kontrole Breloki również wtedy, gdy wejście (thevalue
) jest już zapisany. Zapobiega to dwukrotnemu dodawaniu tego samego certyfikatu lub klucza. Również jeśli określisz innykSecAttrApplicationTag
klucz (który musi być unikalny w odniesieniu do powyższego postu), zakończy się niepowodzeniem.kSecClass
atrybucie jako nazwie tabeli , a określone powyżej wartości tylko jakoprimary key
o odpowiedniej tabeli.kSecAttrAccount
ikSecAttrService
? - czy może programista może wybrać jakąkolwiek semantykę, którą zdecyduje?kSecAttrService
służy do przechowywania usługi,kSecAttrAccount
służy do przechowywania nazwy konta. Można w nich przechowywać różne rzeczy, ale może to być mylące.Któregoś dnia napotkałem błąd (na iOS 7.1), który jest związany z tym pytaniem. Używałem
SecItemCopyMatching
odczytaćkSecClassGenericPassword
pozycję i powracałerrSecItemNotFound
(-25300), mimokSecAttrAccessGroup
,kSecAttrAccount
ikSecAttrService
wszystkie były dopasowując pozycję w pęku kluczy.W końcu doszedłem do wniosku, że
kSecAttrAccessible
to nie pasuje. Wartość w pęku kluczy miała pdmn = dk (kSecAttrAccessibleAlways
), ale używałemkSecAttrAccessibleWhenUnlocked
.Oczywiście ta wartość nie jest potrzebna w pierwszej kolejności
SecItemCopyMatching
, aleOSStatus
nie była onaerrSecParam
anierrSecBadReq
tylkoerrSecItemNotFound
(-25300), co utrudniało jej znalezienie.Ponieważ
SecItemUpdate
doświadczyłem tego samego problemu, ale w tej metodzie nawet użycie tego samegokSecAttrAccessible
wquery
parametrze nie zadziałało. Dopiero całkowite usunięcie tego atrybutu naprawiło to.Mam nadzieję, że ten komentarz pozwoli niektórym z was zaoszczędzić kilka cennych chwil związanych z debugowaniem.
źródło
Odpowiedź udzielona przez @Tammo Freese wydaje się być poprawna (ale nie wymieniając wszystkich kluczy głównych). Szukałem jakiegoś dowodu w dokumentacji. Wreszcie znaleziono:
Dokumentacja Apple wymieniająca klucze główne dla każdej klasy sekretów (cytat poniżej):
źródło
Oto kolejna przydatna informacja na temat wyjątkowości elementu pęku kluczy, którą można znaleźć w sekcji „Zapewnianie możliwości wyszukiwania” na tej stronie z dokumentami firmy Apple .
kSecClassInternetPassword
W przykładzie użyto elementu klasy , ale jest tam uwaga, która mówi:źródło