2012-07-23 7 views
80

Câu hỏi liên quan đến móc khóa của tôi trong iOS (iPhone, iPad, ...). Tôi nghĩ (nhưng không chắc chắn) rằng việc thực hiện các móc khóa trong Mac OS X làm tăng cùng một câu hỏi với cùng một câu trả lời.Điều gì làm cho một mục keychain độc đáo (trong iOS)?


iOS cung cấp năm loại (lớp) của các mặt hàng keychain. Bạn phải chọn một trong những năm giá trị cho khóa kSecClass để xác định loại:

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) 

Sau thời gian dài của việc đọc tài liệu hướng dẫn táo, blog và diễn đàn-mục, tôi phát hiện ra rằng một mục keychain loại kSecClassGenericPassword được nó tính duy nhất từ ​​các thuộc tính kSecAttrAccessGroup, kSecAttrAccountkSecAttrService.

Nếu ba thuộc tính đó trong yêu cầu 1 giống như trong yêu cầu 2, thì bạn sẽ nhận được cùng một mục keychain mật khẩu chung, bất kể thuộc tính nào khác. Nếu một (hoặc hai hoặc tất cả) thuộc tính này thay đổi giá trị của nó thì bạn sẽ nhận được các mục khác nhau.

Nhưng kSecAttrService chỉ có sẵn cho các mặt hàng loại kSecClassGenericPassword, vì vậy nó không thể là một phần của "khóa duy nhất" của một mục thuộc bất kỳ loại nào khác và dường như không có tài liệu nào chỉ ra rõ ràng thuộc tính nào xác định một mục keychain.

Mã mẫu trong lớp "KeychainItemWrapper" của "GenericKeychain" sử dụng thuộc tính kSecAttrGeneric để tạo một mục duy nhất, nhưng đây là lỗi. Hai mục trong ví dụ này chỉ được lưu trữ như hai mục riêng biệt, bởi vì kSecAttrAccessGroup của chúng là khác nhau (một nhóm có nhóm truy cập, phần còn lại cho phép nó miễn phí). Nếu bạn cố gắng thêm mật khẩu thứ 2 mà không có nhóm truy cập, sử dụng số KeychainItemWrapper của Apple, bạn sẽ thất bại.

Vì vậy, xin vui lòng, trả lời câu hỏi của tôi:

  • Có đúng, rằng sự kết hợp của kSecAttrAccessGroup, kSecAttrAccountkSecAttrService là "chìa khóa độc đáo" của một mục keychain có kSecClass là kSecClassGenericPassword?
  • Thuộc tính nào làm cho mục keychain trở thành duy nhất nếu kSecClass của nó không phải là kSecClassGenericPassword?
+1

Có một [mục nhập blog tại đây] (http://useyourloaf.com/blog/2010/04/28/keychain-duplicate-item-when-adding-password.html) về việc này. – bobobobo

Trả lời

134

Các phím chính được như sau (có nguồn gốc từ các tập tin mã nguồn mở từ Apple, xem Schema.m4, KeySchema.m4SecItem.cpp):

  • Đối với một mục keychain của lớp kSecClassGenericPassword, khóa chính là sự kết hợp của kSecAttrAccountkSecAttrService.
  • Đối với một mục keychain của lớp kSecClassInternetPassword, khóa chính là sự kết hợp của kSecAttrAccount, kSecAttrSecurityDomain, kSecAttrServer, kSecAttrProtocol, kSecAttrAuthenticationType, kSecAttrPortkSecAttrPath.
  • Đối với một mục keychain của lớp kSecClassCertificate, khóa chính là sự kết hợp của kSecAttrCertificateType, kSecAttrIssuerkSecAttrSerialNumber.
  • Đối với một mục keychain của lớp kSecClassKey, khóa chính là sự kết hợp của kSecAttrApplicationLabel, kSecAttrApplicationTag, kSecAttrKeyType, kSecAttrKeySizeInBits, kSecAttrEffectiveKeySize, và tác giả, ngày bắt đầu và ngày kết thúc mà không được tiếp xúc bởi SecItem được nêu ra.
  • Đối với một mục keychain của lớp kSecClassIdentity Tôi chưa tìm thấy thông tin về các trường khóa chính trong tệp nguồn mở, nhưng dưới dạng danh tính là tổ hợp khóa cá nhân và chứng chỉ, tôi giả định khóa chính là kết hợp của các trường khóa chính cho kSecClassKeykSecClassCertificate.

Vì mỗi mục keychain thuộc nhóm truy cập keychain, có cảm giác như nhóm truy cập keychain (trường kSecAttrAccessGroup) là trường được thêm vào tất cả các khóa chính này.

+0

Âm thanh như một câu trả lời thực sự tốt! Cảm ơn bạn! Tôi sẽ kiểm tra nó và tôi muốn chờ một hoặc hai ngày để nhận thêm ý kiến ​​từ những người dùng khác, nhưng bạn là một ứng cử viên nóng cho 50 điểm từ tiền thưởng. –

+3

Câu trả lời hay! Tôi đang làm việc cho một số ngày trên thực hiện một wrapper Keychain chung cho các chứng chỉ và khóa riêng. Đó là rất nhiều khác nhau để mã mẫu của Apple chỉ lưu trữ thông tin đăng nhập chuỗi (tên người dùng/mật khẩu). Tuy nhiên, tôi đã phát hiện ra rằng khi bạn đặt 'kSecClass' thành' kSecClassCertificate' hoặc 'kSecClassKey', Keychain cũng sẽ kiểm tra nếu mục nhập (' giá trị') đã được lưu trữ. Điều này ngăn không cho thêm cùng một chứng chỉ hoặc khóa hai lần. Ngoài ra nếu bạn chỉ định một 'kSecAttrApplicationTag' khác cho một khóa (phải là duy nhất, liên quan đến bài viết ở trên) thì nó sẽ thất bại. – Chris

+0

@Chris Thật tuyệt khi biết về kiểm tra bổ sung đó, cảm ơn! –

7

Tôi đã gặp lỗi vào ngày khác (trên iOS 7.1) có liên quan đến câu hỏi này. Tôi đã sử dụng SecItemCopyMatching để đọc một mặt hàng kSecClassGenericPassword và nó giữ lại errSecItemNotFound (-25300) mặc dù kSecAttrAccessGroup, kSecAttrAccountkSecAttrService đều khớp với mặt hàng đó trong chuỗi khóa.

Cuối cùng tôi đã tìm ra rằng kSecAttrAccessible không khớp. Giá trị trong keychain được giữ pdmn = dk (kSecAttrAccessibleAlways), nhưng tôi đã sử dụng kSecAttrAccessibleWhenUnlocked.

Tất nhiên giá trị này là không cần thiết ở nơi đầu tiên cho SecItemCopyMatching, nhưng OSStatus không errSecParam cũng không errSecBadReq nhưng chỉ errSecItemNotFound (-25.300) mà làm cho nó một chút khó khăn để tìm thấy.

Đối với SecItemUpdate Tôi đã gặp sự cố tương tự nhưng trong phương pháp này thậm chí sử dụng cùng một thông số kSecAttrAccessible trong thông số query không hoạt động. Chỉ loại bỏ hoàn toàn thuộc tính này đã sửa nó.

Tôi hy vọng nhận xét này sẽ tiết kiệm được một vài khoảnh khắc gỡ lỗi quý giá cho một số bạn.