Điều gì làm cho một mục móc khóa trở nên độc đáo (trong iOS)?


104

Câu hỏi của tôi liên quan đến móc khóa trong iOS (iPhone, iPad, ...). Tôi nghĩ (nhưng không chắc) rằng việc triển khai móc khóa trong Mac OS X đặt ra câu hỏi tương tự với cùng câu trả lời.


iOS cung cấp năm loại (lớp) mặt hàng chuỗi khóa. Bạn phải chọn một trong 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 tài liệu táo đọc, 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 tính độc đáo của nó 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 chuỗi khóa 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 vật phẩm khác nhau.

Nhưng kSecAttrServicechỉ có sẵn cho các mặt hàng thuộc 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ặt hàng 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 duy nhất một mặt hàng chuỗi khóa.

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

Vì vậy, 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, kSecAttrAccountkSecAttrServicelà "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ột mặt hàng trong chuỗi khóa là duy nhất nếu kSecClasskhông phải là thuộc tính kSecClassGenericPassword?

1
Có một mục blog ở đây về điều này.
bobobobo

Câu trả lời:


179

Các khóa chính như sau (lấy từ các tệp nguồn mở của 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, các 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, các khóa chính là sự kết hợp của kSecAttrApplicationLabel, kSecAttrApplicationTag, kSecAttrKeyType, kSecAttrKeySizeInBits, kSecAttrEffectiveKeySize, và các 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, kSecClassIdentitytôi không tìm thấy thông tin về các trường khóa chính trong tệp nguồn mở, nhưng vì danh tính là sự kết hợp của khóa cá nhân và chứng chỉ, tôi giả sử khóa chính là sự kết hợp của khóa chính trường cho kSecClassKeykSecClassCertificate.

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


Nghe có vẻ như là 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 đợi một hoặc hai ngày để có thêm nhận xét từ những người dùng khác, nhưng bạn là một ứng cử viên nóng bỏng cho +50 điểm từ tiền thưởng.
Hubert Schölnast

3
Câu trả lời chính xác! Tôi đang làm việc trong một số ngày để triển khai trình bao bọc Chuỗi khóa chung cho các chứng chỉ và khóa cá nhân. Điều đó khác rất nhiều so với 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 thiết lập kSecClassđể kSecClassCertificatehoặc kSecClassKeykiểm tra Keychain còn nếu mục nhập (các value) đã được lưu trữ. Điều này ngăn cản việc 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 khóa khác kSecAttrApplicationTagcho khóa (phải là duy nhất, liên quan đến bài đăng ở trên) thì nó sẽ không thành công.
Chris

1
Có thể hữu ích khi kSecClasscoi thuộc tính là tên bảng và các giá trị được chỉ định ở trên chỉ là primary keycủa bảng tương ứng.
bobobobo

2
Ngữ nghĩa của kSecAttrAccountvà là kSecAttrServicegì? - hoặc lập trình viên có thể chọn bất kỳ ngữ nghĩa nào mà cô ấy quyết định?
wcochran

1
kSecAttrServicelà để lưu trữ dịch vụ, kSecAttrAccountlà để lưu trữ tên tài khoản. Bạn có thể lưu trữ những thứ khác nhau trong chúng, nhưng điều đó có thể gây nhầm lẫn.
Tammo Freese

9

Tôi đã gặp một lỗi vào ngày hôm trướ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 kSecClassGenericPasswordmục và nó giữ trở về errSecItemNotFound(-25.300) mặc dù kSecAttrAccessGroup, kSecAttrAccountkSecAttrServicetất cả đều phù hợp với các mục trong keychain.

Cuối cùng tôi nhận ra điều đó kSecAttrAccessiblekhông phù hợp. Giá trị trong chuỗi khóa được giữ là pdmn = dk ( kSecAttrAccessibleAlways), nhưng tôi đang sử dụng kSecAttrAccessibleWhenUnlocked.

Tất nhiên ngay từ đầu giá trị này không cần thiết SecItemCopyMatching, nhưng OSStatuskhông phải errSecParamcũng không errSecBadReqmà chỉ errSecItemNotFound(-25300) khiến việc tìm kiếm hơi khó.

Đối với SecItemUpdatetôi đã trải qua cùng một vấn đề nhưng trong phương pháp này thậm chí sử dụng cùng một kSecAttrAccessibletrong querysố không làm việc. Chỉ loại bỏ hoàn toàn thuộc tính này mới sửa nó.

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


4

Câu trả lời do @Tammo Freese đưa ra dường như đúng (nhưng không đề cập đến tất cả các khóa chính). Tôi đã tìm kiếm một số bằng chứng trong tài liệu. Cuối cùng đã tìm thấy:

Tài liệu Apple đề cập đến các khóa chính cho từng lớp bí mật (trích dẫn bên dưới):

Hệ thống coi một mục là bản sao của một chuỗi khóa nhất định khi chuỗi khóa đó đã có một mục cùng loại với cùng một bộ khóa chính tổng hợp. Mỗi lớp mục keychain có một bộ khóa chính khác nhau, mặc dù một số thuộc tính được sử dụng chung cho tất cả các lớp. Cụ thể, nếu có thể, kSecAttrSynchronizable và kSecAttrAccessGroup là một phần của bộ khóa chính . Các khóa chính bổ sung cho mỗi lớp được liệt kê bên dưới:

  • Đối với mật khẩu chung, khóa chính bao gồm kSecAttrAccount và kSecAttrService.
  • Đối với mật khẩu internet, các khóa chính bao gồm kSecAttrAccount, kSecAttrSecurityDomain, kSecAttrServer, kSecAttrProtocol, kSecAttrAuthenticationType, kSecAttrPort và kSecAttrPath.
  • Đối với chứng chỉ, các khóa chính bao gồm kSecAttrCertificateType, kSecAttrIssuer và kSecAttrSerialNumber.
  • Đối với các mục chính, các khóa chính bao gồm kSecAttrKeyClass, kSecAttrKeyType, kSecAttrApplicationLabel, kSecAttrApplicationTag, kSecAttrKeySizeInBits và kSecAttrEffectiveKeySize.
  • Đối với các mục nhận dạng, là một chứng chỉ và một khóa cá nhân được nhóm lại với nhau, các khóa chính giống như đối với một chứng chỉ. Vì khóa riêng tư có thể được chứng nhận nhiều lần, nên tính duy nhất của chứng chỉ sẽ xác định danh tính.

Mặc dù liên kết này có thể trả lời câu hỏi, nhưng tốt hơn hết bạn nên đưa các phần thiết yếu của câu trả lời vào đây và cung cấp liên kết để tham khảo. Các câu trả lời chỉ có liên kết có thể trở nên không hợp lệ nếu trang được liên kết thay đổi. - Từ xét
PwC

đã đồng ý, mặc dù trong trường hợp này, nó có nghĩa là sao chép toàn bộ liên kết.
Julian Król

0

Dưới đây là một thông tin hữu ích khác về tính duy nhất của một mặt hàng móc khóa, được tìm thấy trong phần "Đảm bảo khả năng tìm kiếm" của trang tài liệu Apple này .

Để có thể tìm thấy mặt hàng sau này, bạn sẽ sử dụng kiến ​​thức của mình về các thuộc tính của nó. Trong ví dụ này, máy chủ và tài khoản là đặc điểm phân biệt của mặt hàng. Đối với các thuộc tính không đổi (ở đây, máy chủ), hãy sử dụng cùng một giá trị trong khi tra cứu. Ngược lại, thuộc tính tài khoản là động, vì nó chứa một giá trị do người dùng cung cấp trong thời gian chạy. Miễn là ứng dụng của bạn không bao giờ thêm các mục tương tự với các thuộc tính khác nhau (chẳng hạn như mật khẩu cho các tài khoản khác nhau trên cùng một máy chủ), bạn có thể bỏ qua các thuộc tính động này dưới dạng thông số tìm kiếm và thay vào đó truy xuất chúng cùng với mục. Kết quả là khi tra cứu mật khẩu, bạn cũng nhận được tên người dùng tương ứng.

Nếu ứng dụng của bạn thêm các mục với các thuộc tính động khác nhau, bạn sẽ cần có cách để chọn trong số chúng trong quá trình truy xuất. Một tùy chọn là ghi lại thông tin về các mục theo cách khác. Ví dụ: nếu bạn lưu giữ hồ sơ của người dùng trong mô hình Dữ liệu cốt lõi, bạn sẽ lưu tên người dùng ở đó sau khi sử dụng các dịch vụ chuỗi khóa để lưu trữ trường mật khẩu. Sau đó, bạn sử dụng tên người dùng lấy từ mô hình dữ liệu của mình để điều kiện tìm kiếm mật khẩu.

Trong các trường hợp khác, có thể có ý nghĩa khi mô tả thêm đặc điểm của mặt hàng bằng cách thêm nhiều thuộc tính hơn. Ví dụ: bạn có thể bao gồm kSecAttrLabelthuộc tính trong truy vấn thêm ban đầu, cung cấp một chuỗi đánh dấu mục cho mục đích cụ thể. Sau đó, bạn sẽ có thể sử dụng thuộc tính này để thu hẹp tìm kiếm của mình sau này.

Mục của lớp kSecClassInternetPasswordđã được sử dụng trong ví dụ, nhưng có một ghi chú cho biết:

Các dịch vụ chuỗi khóa cũng cung cấp lớp mục kSecClassGenericPassword liên quan. Mật khẩu chung tương tự về hầu hết các khía cạnh với mật khẩu Internet, nhưng chúng thiếu một số thuộc tính cụ thể để truy cập từ xa (ví dụ: chúng không có thuộc tính kSecAttrServer). Khi bạn không cần các thuộc tính bổ sung này, hãy sử dụng mật khẩu chung.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.