2012-07-23 16 views
80

Moje pytanie dotyczy breloczków w iOS (iPhone, iPad, ...). Myślę (ale nie jestem pewien), że implementacja breloków pod Mac OS X rodzi to samo pytanie z tą samą odpowiedzią.Co sprawia, że ​​element z pękiem kluczy jest wyjątkowy (w iOS)?


System iOS udostępnia pięć typów (klas) artykułów z pękiem kluczy. Musisz wybrać jedną z tych pięciu wartości dla klucza kSecClass do określenia typu:

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 forum-wpisy, dowiedziałem się, że brelok poz typu kSecClassGenericPassword dostaje swoją wyjątkowość z atrybutów kSecAttrAccessGroup,i kSecAttrService.

Jeśli te trzy atrybuty w żądaniu 1 są takie same jak w żądaniu 2, otrzymasz ten sam ogólny brelok z hasłem hasła, niezależnie od innych atrybutów. Jeśli jeden (lub dwa lub wszystkie) z tych atrybutów zmienia swoją wartość, otrzymujesz różne przedmioty.

Ale pozycja kSecAttrService jest dostępna tylko dla elementów typu kSecClassGenericPassword, więc nie może być częścią "klucza niepowtarzalnego" elementu dowolnego innego typu i wydaje się, że nie ma dokumentacji, która jasno wskazywałaby, które atrybuty są unikatowe. określić element pęku kluczy.

Przykładowy kod w klasie "KeychainItemWrapper" z "GenericKeychain" używa atrybutu kSecAttrGeneric, aby uczynić przedmiot wyjątkowym, ale jest to błąd. Dwa wpisy w tym przykładzie są przechowywane tylko jako dwa odrębne wpisy, ponieważ ich kSecAttrAccessGroup jest inny (jeden ma zestaw grup dostępu, a drugi pozwala na uwolnienie). Jeśli spróbujesz dodać drugie hasło bez grupy dostępu, używając urządzenia Apple KeychainItemWrapper, to się nie powiedzie.

Więc, proszę odpowiedzieć na moje pytania:

  • Czy to prawda, że ​​kombinacja kSecAttrAccessGroup, kSecAttrAccount i kSecAttrService jest „unikalny klucz” z pęku kluczy elementu, którego kSecClass jest kSecClassGenericPassword?
  • Jakie atrybuty powodują, że element keychain jest unikalny, jeśli jego kSecClass nie jest kSecClassGenericPassword?
+1

Tutaj znajduje się [wpis na blogu] (http://useyourloaf.com/blog/2010/04/28/keychain-duplicate-item-when-adding-password.html). – bobobobo

Odpowiedz

134

Klucze podstawowe są następująco (pochodzące z otwartych plików źródłowych z Apple, patrz Schema.m4, KeySchema.m4 i SecItem.cpp):

  • Dla pęku kluczy pozycji klasy kSecClassGenericPassword, klucz podstawowy jest kombinacją kSecAttrAccount i kSecAttrService.
  • Dla pęku kluczy pozycji klasy kSecClassInternetPassword, klucz podstawowy jest kombinacją kSecAttrAccount, kSecAttrSecurityDomain, kSecAttrServer, kSecAttrProtocol, kSecAttrAuthenticationType, kSecAttrPort i kSecAttrPath.
  • Dla elementu z pękiem kluczy klasy kSecClassCertificate klucz podstawowy jest kombinacją kSecAttrCertificateType, kSecAttrIssuer i kSecAttrSerialNumber.
  • Dla pęku kluczy pozycji klasy 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.
  • Dla elementu z pękiem kluczy klasy kSecClassIdentity Nie znalazłem informacji na temat pól kluczy podstawowych w plikach open source, ale jako że tożsamość jest kombinacją klucza prywatnego i certyfikatu, zakładam, że klucz podstawowy to połączenie podstawowych pól klucza dla kSecClassKey i kSecClassCertificate.

Ponieważ każdy element pęku kluczy należy do grupy dostępu do pęku kluczy, wygląda na to, że grupa dostępu do pęku kluczy (pole kSecAttrAccessGroup) jest dodatkowym polem dla wszystkich kluczy podstawowych.

+0

Brzmi jak naprawdę dobra odpowiedź! Dziękuję Ci! Sprawdzę to i chcę poczekać jeden lub dwa dni na dodatkowe komentarze od innych użytkowników, ale jesteś gorącym kandydatem na +50 punktów z nagrody. –

+3

Świetna odpowiedź! Pracuję przez kilka dni nad implementacją ogólnego opakowania Brelok dla certyfikatów i kluczy prywatnych. To dużo różni się od przykładowego kodu firmy Apple, który przechowuje jedynie referencje łańcuchowe (nazwa użytkownika/hasło). Jednakże dowiedziałem się, że po ustawieniu 'kSecClass' na' kSecClassCertificate' lub 'kSecClassKey' Keychain sprawdza również, czy wpis (" wartość ") jest już zapisany. Zapobiega to dwukrotnemu dodaniu tego samego certyfikatu lub klucza. Również jeśli podasz inny klucz 'kSecAttrApplicationTag' dla klucza (który musi być unikalny, w odniesieniu do postu powyżej), to się nie powiedzie. – Chris

+0

@Chris Dobrze wiedzieć o tym dodatkowym czeku, dzięki! –

7

Uderzyłem się w błąd na drugi dzień (na iOS 7.1), który jest związany z tym pytaniem. Używałem SecItemCopyMatching do czytania elementu kSecClassGenericPassword i wracałem errSecItemNotFound (-25300), mimo że kSecAttrAccessGroup, kSecAttrAccount i kSecAttrService wszystkie pasowały do ​​elementu w pęku kluczy.

W końcu zorientowałem się, że kSecAttrAccessible nie pasuje. Wartość w pęku kluczy zawierała pdmn = dk (kSecAttrAccessibleAlways), ale używałem kSecAttrAccessibleWhenUnlocked.

Oczywiście wartość ta nie jest potrzebne w pierwszej kolejności dla SecItemCopyMatching, ale OSStatus nie errSecParam ani errSecBadReq ale tylko errSecItemNotFound (-25300), co sprawiło, że nieco trudne do znalezienia było.

Dla SecItemUpdate Doświadczyłem tego samego problemu, ale w tej metodzie nawet przy użyciu tego samego parametru kSecAttrAccessible w parametrze query nie działa. Tylko całkowite usunięcie tego atrybutu rozwiązało problem.

Mam nadzieję, że ten komentarz uratuje kilka cennych momentów do debugowania dla niektórych z was.

Powiązane problemy