อะไรทำให้ไอเท็มพวงกุญแจไม่เหมือนใคร (ใน iOS)


104

คำถามของฉันเกี่ยวกับพวงกุญแจใน iOS (iPhone, iPad, ... ) ฉันคิดว่า (แต่ไม่แน่ใจ) ว่าการใช้งานพวงกุญแจภายใต้ Mac OS X ทำให้เกิดคำถามเดียวกันกับคำตอบเดียวกัน


iOS มีรายการพวงกุญแจห้าประเภท (คลาส) คุณต้องเลือกหนึ่งในห้าค่าสำหรับคีย์kSecClassเพื่อกำหนดประเภท:

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)

หลังจากเป็นเวลานานของเอกสารแอปเปิ้ลอ่านบล็อกและรายการฟอรั่ม, ฉันพบว่ารายการพวงกุญแจจากประเภทนี้kSecClassGenericPasswordได้รับความเป็นเอกลักษณ์จากคุณลักษณะkSecAttrAccessGroup, และkSecAttrAccountkSecAttrService

หากแอตทริบิวต์ทั้งสามในคำขอ 1 เหมือนกับในคำขอ 2 คุณจะได้รับรายการพวงกุญแจรหัสผ่านทั่วไปเหมือนกันโดยไม่คำนึงถึงแอตทริบิวต์อื่น ๆ หากแอตทริบิวต์หนึ่ง (หรือสองรายการหรือทั้งหมด) เปลี่ยนค่าคุณจะได้รับรายการที่แตกต่างกัน

แต่kSecAttrServiceใช้ได้เฉพาะกับสินค้าประเภทkSecClassGenericPasswordดังนั้นจึงไม่สามารถเป็นส่วนหนึ่งของ "คีย์เฉพาะ" ของรายการประเภทอื่น ๆ ได้และดูเหมือนว่าจะไม่มีเอกสารประกอบที่ชี้ให้เห็นอย่างชัดเจนว่าแอตทริบิวต์ใดกำหนดรายการพวงกุญแจโดยเฉพาะ

โค้ดตัวอย่างในคลาส "KeychainItemWrapper" ของ "GenericKeychain" ใช้แอตทริบิวต์kSecAttrGenericเพื่อทำให้ไอเท็มไม่ซ้ำกัน แต่นี่เป็นข้อบกพร่อง สองรายการในตัวอย่างนี้จะถูกจัดเก็บเป็นสองรายการที่แตกต่างกันเท่านั้นเนื่องจากรายการเหล่าkSecAttrAccessGroupนี้แตกต่างกัน (รายการหนึ่งมีการตั้งค่ากลุ่มการเข้าถึงส่วนอีกรายการหนึ่งปล่อยให้เป็นอิสระ) หากคุณพยายามเพิ่มรหัสผ่านที่ 2 โดยไม่มีกลุ่มการเข้าถึงโดยใช้ของ Apple KeychainItemWrapperคุณจะล้มเหลว

ดังนั้นโปรดตอบคำถามของฉัน:

  • มันเป็นความจริงว่าการรวมกันของkSecAttrAccessGroup, kSecAttrAccountและkSecAttrServiceเป็น "กุญแจสำคัญที่ไม่ซ้ำกัน" ของรายการพวงกุญแจที่มี kSecClass คือkSecClassGenericPassword?
  • ซึ่งคุณลักษณะที่ทำให้รายการพวงกุญแจที่ไม่ซ้ำกันถ้าkSecClassไม่ได้kSecClassGenericPassword?

1
มีรายการบล็อกที่นี่เกี่ยวกับเรื่องนี้
bobobobo

คำตอบ:


179

คีย์หลักมีดังนี้ (มาจากไฟล์โอเพนซอร์สจาก Apple โปรดดูSchema.m4 , KeySchema.m4และSecItem.cpp ):

  • สำหรับรายการพวงกุญแจของการเรียนkSecClassGenericPassword, คีย์หลักคือการรวมกันของ และkSecAttrAccountkSecAttrService
  • สำหรับรายการพวงกุญแจของการเรียนkSecClassInternetPassword, คีย์หลักคือการรวมกันของkSecAttrAccount, kSecAttrSecurityDomain, kSecAttrServer, kSecAttrProtocol, kSecAttrAuthenticationType, และkSecAttrPortkSecAttrPath
  • สำหรับรายการพวงกุญแจของการเรียนkSecClassCertificate, คีย์หลักคือการรวมกันของkSecAttrCertificateType, และkSecAttrIssuerkSecAttrSerialNumber
  • สำหรับรายการพวงกุญแจของการเรียนkSecClassKey, คีย์หลักคือการรวมกันของkSecAttrApplicationLabel, kSecAttrApplicationTag, kSecAttrKeyType, kSecAttrKeySizeInBits, kSecAttrEffectiveKeySizeและผู้สร้างวันที่เริ่มต้นและสิ้นสุดวันที่ไม่ได้รับการเปิดเผยโดย SecItem เลย
  • สำหรับรายการพวงกุญแจของคลาสkSecClassIdentityฉันไม่พบข้อมูลในช่องคีย์หลักในไฟล์โอเพนซอร์ส แต่เนื่องจากข้อมูลประจำตัวคือการรวมกันของคีย์ส่วนตัวและใบรับรองฉันถือว่าคีย์หลักคือการรวมกันของคีย์หลัก ฟิลด์สำหรับkSecClassKeyและkSecClassCertificate.

เนื่องจากรายการพวงกุญแจแต่ละรายการอยู่ในกลุ่มการเข้าถึงพวงกุญแจจึงรู้สึกว่ากลุ่มการเข้าถึงพวงกุญแจ (ฟิลด์kSecAttrAccessGroup) เป็นช่องที่เพิ่มให้กับคีย์หลักทั้งหมดเหล่านี้


ฟังดูเป็นคำตอบที่ดีจริงๆ! ขอบคุณ! ฉันจะตรวจสอบและฉันต้องการรอหนึ่งหรือสองวันสำหรับความคิดเห็นเพิ่มเติมจากผู้ใช้รายอื่น แต่คุณเป็นผู้สมัครที่ได้รับคะแนน +50 จากเงินรางวัล
Hubert Schölnast

3
ตอบโจทย์มาก! ฉันกำลังทำงานอยู่หลายวันเพื่อใช้งานพวงกุญแจทั่วไปสำหรับใบรับรองและคีย์ส่วนตัว ซึ่งแตกต่างอย่างมากกับโค้ดตัวอย่างของ Apple ที่เก็บเฉพาะข้อมูลรับรองสตริง (ชื่อผู้ใช้ / รหัสผ่าน) แต่ผมได้พบว่าเมื่อคุณตั้งค่าkSecClassการkSecClassCertificateหรือkSecClassKeyตรวจสอบพวงกุญแจยังถ้ารายการ (คนvalue) จะถูกเก็บไว้อยู่แล้ว ซึ่งจะป้องกันไม่ให้เพิ่มใบรับรองหรือคีย์เดียวกันซ้ำสองครั้ง นอกจากนี้หากคุณระบุkSecAttrApplicationTagคีย์อื่น (ซึ่งต้องไม่ซ้ำกันเกี่ยวกับโพสต์ด้านบน) จะล้มเหลว
คริส

1
การคิดkSecClassแอตทริบิวต์เป็นชื่อตารางอาจช่วยได้และค่าที่ระบุด้านบนเป็นเพียงprimary keyตารางที่เกี่ยวข้อง
bobobobo

2
อะไรคือความหมายของkSecAttrAccountและkSecAttrService? - หรือโปรแกรมเมอร์สามารถเลือกความหมายที่เธอตัดสินใจได้หรือไม่?
wcochran

1
kSecAttrServiceมีไว้สำหรับจัดเก็บบริการkSecAttrAccountมีไว้สำหรับจัดเก็บชื่อบัญชี คุณสามารถจัดเก็บสิ่งของต่างๆไว้ในนั้นได้ แต่อาจทำให้สับสนได้
Tammo Freese

9

วันก่อนฉันพบข้อผิดพลาด (บน iOS 7.1) ที่เกี่ยวข้องกับคำถามนี้ ฉันถูกใช้SecItemCopyMatchingในการอ่านkSecClassGenericPasswordรายการและมันยังคงกลับมาerrSecItemNotFound(-25300) แม้ว่าkSecAttrAccessGroup, kSecAttrAccountและkSecAttrServiceทุกคนที่ตรงกับรายการในพวงกุญแจ

ในที่สุดฉันก็พบว่าkSecAttrAccessibleมันไม่ตรงกัน ค่าในพวงกุญแจถือ pdmn = dk ( kSecAttrAccessibleAlways) แต่ฉันใช้kSecAttrAccessibleWhenUnlocked.

แน่นอนว่าค่านี้ไม่จำเป็นในตอนแรกSecItemCopyMatchingแต่OSStatusไม่ใช่errSecParamหรือerrSecBadReqแต่เป็นเพียงerrSecItemNotFound(-25300) ซึ่งทำให้หายากเล็กน้อย

สำหรับSecItemUpdateฉันเคยประสบปัญหาเดียวกัน แต่ในวิธีนี้แม้จะใช้พารามิเตอร์เดียวกันkSecAttrAccessibleในqueryพารามิเตอร์ก็ไม่ได้ผล เฉพาะการลบแอตทริบิวต์นี้อย่างสมบูรณ์เท่านั้นที่แก้ไขได้

ฉันหวังว่าความคิดเห็นนี้จะช่วยประหยัดช่วงเวลาในการแก้ไขจุดบกพร่องอันมีค่าสำหรับบางคน


4

คำตอบของ @Tammo Freese ดูเหมือนจะถูกต้อง (แต่ไม่ได้กล่าวถึงคีย์หลักทั้งหมด) ฉันกำลังค้นหาหลักฐานบางอย่างในเอกสารประกอบ ในที่สุดก็พบ:

เอกสารของ Apple กล่าวถึงคีย์หลักสำหรับความลับแต่ละคลาส (อ้างอิงด้านล่าง):

ระบบจะพิจารณาว่าไอเท็มซ้ำกันสำหรับพวงกุญแจที่กำหนดเมื่อพวงกุญแจนั้นมีไอเท็มคลาสเดียวกันที่มีคีย์หลักผสมชุดเดียวกันอยู่แล้ว รายการพวงกุญแจแต่ละคลาสมีชุดคีย์หลักที่แตกต่างกันแม้ว่าจะมีการใช้แอตทริบิวต์บางอย่างเหมือนกันในทุกคลาส โดยเฉพาะอย่างยิ่งที่ใช้บังคับ kSecAttrSynchronizable และ kSecAttrAccessGroup เป็นส่วนหนึ่งของชุดของคีย์หลัก คีย์หลักสำหรับแต่ละคลาสเพิ่มเติมมีดังต่อไปนี้:

  • สำหรับรหัสผ่านทั่วไปคีย์หลักได้แก่ kSecAttrAccount และ kSecAttrService
  • สำหรับรหัสผ่านอินเทอร์เน็ตคีย์หลักได้แก่ kSecAttrAccount, kSecAttrSecurityDomain, kSecAttrServer, kSecAttrProtocol, kSecAttrAuthenticationType, kSecAttrPort และ kSecAttrPath
  • สำหรับใบรับรองคีย์หลักได้แก่ kSecAttrCertificateType, kSecAttrIssuer และ kSecAttrSerialNumber
  • สำหรับรายการหลักคีย์หลักได้แก่ kSecAttrKeyClass, kSecAttrKeyType, kSecAttrApplicationLabel, kSecAttrApplicationTag, kSecAttrKeySizeInBits และ kSecAttrEffectiveKeySize
  • สำหรับรายการข้อมูลประจำตัวซึ่ง ได้แก่ ใบรับรองและคีย์ส่วนตัวที่รวมเข้าด้วยกันคีย์หลักจะเหมือนกับใบรับรอง เนื่องจากคีย์ส่วนตัวอาจได้รับการรับรองมากกว่าหนึ่งครั้งความเป็นเอกลักษณ์ของใบรับรองจึงเป็นตัวกำหนดว่าเป็นตัวตน

แม้ว่าลิงก์นี้อาจตอบคำถามได้ แต่ควรรวมส่วนสำคัญของคำตอบไว้ที่นี่และระบุลิงก์เพื่อการอ้างอิง คำตอบแบบลิงก์เท่านั้นอาจไม่ถูกต้องหากหน้าที่เชื่อมโยงเปลี่ยนไป - จากรีวิว
pwc

ตกลงแม้ว่าในกรณีนี้จะหมายถึงการคัดลอกลิงก์ทั้งหมด
Julian Król

0

นี่คือชิ้นส่วนของข้อมูลที่เป็นประโยชน์เกี่ยวกับเอกลักษณ์ของรายการพวงกุญแจอื่นที่พบในส่วน "การตรวจสอบให้แน่ใจ Searchability" ของหน้านี้แอปเปิ้ลเอกสาร

เพื่อให้สามารถค้นหารายการได้ในภายหลังคุณจะต้องใช้ความรู้เกี่ยวกับคุณสมบัติของมัน ในตัวอย่างนี้เซิร์ฟเวอร์และบัญชีเป็นลักษณะเฉพาะของรายการ สำหรับแอตทริบิวต์คงที่ (ที่นี่คือเซิร์ฟเวอร์) ให้ใช้ค่าเดียวกันในระหว่างการค้นหา ในทางตรงกันข้ามแอตทริบิวต์บัญชีเป็นแบบไดนามิกเนื่องจากมีค่าที่ผู้ใช้ระบุไว้ในขณะรันไทม์ ตราบใดที่แอปของคุณไม่เคยเพิ่มรายการที่คล้ายกันซึ่งมีแอตทริบิวต์ที่แตกต่างกัน (เช่นรหัสผ่านสำหรับบัญชีต่างกันบนเซิร์ฟเวอร์เดียวกัน) คุณสามารถละเว้นแอตทริบิวต์แบบไดนามิกเหล่านี้เป็นพารามิเตอร์การค้นหาและดึงข้อมูลเหล่านี้มาพร้อมกับรายการแทนได้ ดังนั้นเมื่อคุณค้นหารหัสผ่านคุณจะได้รับชื่อผู้ใช้ที่เกี่ยวข้องด้วย

หากแอปของคุณเพิ่มรายการที่มีแอตทริบิวต์ไดนามิกที่แตกต่างกันคุณจะต้องมีวิธีเลือกระหว่างการดึงข้อมูล ทางเลือกหนึ่งคือการบันทึกข้อมูลเกี่ยวกับรายการด้วยวิธีอื่น ตัวอย่างเช่นหากคุณเก็บบันทึกของผู้ใช้ในแบบจำลองข้อมูลหลักคุณจะเก็บชื่อผู้ใช้ไว้ที่นั่นหลังจากใช้บริการพวงกุญแจเพื่อจัดเก็บฟิลด์รหัสผ่าน ในภายหลังคุณใช้ชื่อผู้ใช้ที่ดึงมาจากโมเดลข้อมูลของคุณเพื่อกำหนดเงื่อนไขการค้นหารหัสผ่าน

ในกรณีอื่น ๆ คุณควรกำหนดลักษณะของรายการเพิ่มเติมโดยการเพิ่มแอตทริบิวต์เพิ่มเติม ตัวอย่างเช่นคุณอาจรวมkSecAttrLabelแอตทริบิวต์ไว้ในคำสั่งเพิ่มต้นฉบับโดยระบุสตริงที่ทำเครื่องหมายรายการสำหรับวัตถุประสงค์เฉพาะ จากนั้นคุณจะสามารถใช้แอตทริบิวต์นี้เพื่อ จำกัด การค้นหาของคุณในภายหลัง

ตัวอย่างมีการใช้ Item of class kSecClassInternetPasswordแต่มีหมายเหตุว่า:

บริการพวงกุญแจยังมีคลาสรายการ kSecClassGenericPassword ที่เกี่ยวข้อง รหัสผ่านทั่วไปมีความคล้ายคลึงกับรหัสผ่านอินเทอร์เน็ตเกือบทุกประการ แต่ไม่มีคุณลักษณะเฉพาะสำหรับการเข้าถึงระยะไกล (ตัวอย่างเช่นไม่มีแอตทริบิวต์ kSecAttrServer) เมื่อคุณไม่ต้องการคุณสมบัติพิเศษเหล่านี้ให้ใช้รหัสผ่านทั่วไปแทน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.