Android 9 รองรับการหมุนเวียนคีย์ของ APK ซึ่งช่วยให้แอปเปลี่ยนคีย์การรับรองได้เป็นส่วนหนึ่งของการอัปเดต APK APK ต้องระบุระดับความน่าเชื่อถือระหว่างคีย์ App Signing ใหม่และคีย์ App Signing เก่าเพื่อให้การหมุนเวียนคีย์ใช้งานได้จริง เราได้อัปเดตรูปแบบการรับรอง APK จาก v2 เป็น v3 เพื่อรองรับการหมุนเวียนคีย์ ซึ่งจะช่วยให้ใช้คีย์ใหม่และคีย์เก่าได้ V3 จะเพิ่มข้อมูลเกี่ยวกับเวอร์ชัน SDK ที่รองรับและโครงสร้างหลักฐานการหมุนเวียนลงในบล็อกการรับรอง APK
บล็อกการรับรอง APK
ระบบจะจัดเก็บลายเซ็น APK เวอร์ชัน 2 และ 3 ไว้ในบล็อกการรับรอง APK ซึ่งอยู่ก่อนไดเรกทอรีกลาง ZIP โดยตรง เพื่อรักษาความสามารถในการใช้งานร่วมกันย้อนหลังกับรูปแบบ APK เวอร์ชัน 1
รูปแบบบล็อกการรับรอง APK ของ v3 เหมือนกับ v2 ลายเซ็น v3 ของ APK จะจัดเก็บเป็นคู่รหัส-ค่าที่มีรหัส 0xf05368c0
บล็อก APK Signature Scheme v3
รูปแบบ v3 ออกแบบมาให้คล้ายกับรูปแบบ v2 อย่างมาก โดยจะมีรูปแบบทั่วไปเหมือนกันและรองรับรหัสอัลกอริทึมลายเซ็น ขนาดคีย์ และเส้นโค้ง EC เดียวกัน
แต่รูปแบบ v3 จะเพิ่มข้อมูลเกี่ยวกับเวอร์ชัน SDK ที่รองรับและโครงสร้าง proof-of-rotation
รูปแบบ
ระบบจะจัดเก็บบล็อก APK Signature Scheme v3 ไว้ในบล็อกการรับรอง APK ภายใต้รหัส 0xf05368c0
รูปแบบของบล็อก APK Signature Scheme v3 เป็นไปตามรูปแบบของ v2 ดังนี้
- ลำดับที่มีความยาวนำหน้าของ
signer
ที่มีความยาวนำหน้า ดังนี้signed data
ที่มีความยาวนำหน้า:- ลำดับที่มีความยาวนำหน้าของ
digests
ที่มีความยาวนำหน้า ดังนี้signature algorithm ID
(4 ไบต์)digest
(มีความยาวนำหน้า)
- ลำดับ X.509 ที่มีความยาวนำหน้า
certificates
:- X.509
certificate
ที่มีความยาวนำหน้า (รูปแบบ ASN.1 DER)
- X.509
minSDK
(uint32) - ระบบควรละเว้นผู้ลงนามรายนี้หากเวอร์ชันแพลตฟอร์มต่ำกว่าหมายเลขนี้maxSDK
(uint32) - ระบบควรละเว้นผู้ลงนามรายนี้หากเวอร์ชันแพลตฟอร์มสูงกว่าตัวเลขนี้- ลำดับที่มีความยาวนำหน้าของ
additional attributes
ที่มีความยาวนำหน้า ดังนี้ID
(uint32)value
(ความยาวแปรผัน: ความยาวของแอตทริบิวต์เพิ่มเติม - 4 ไบต์)ID - 0x3ba06f8c
value -
โครงสร้างหลักฐานแสดงการหมุนเวียนคีย์
- ลำดับที่มีความยาวนำหน้าของ
minSDK
(uint32) - ค่า minSDK ที่ซ้ำกันในส่วนข้อมูลที่เซ็นชื่อ - ใช้เพื่อข้ามการยืนยันลายเซ็นนี้หากแพลตฟอร์มปัจจุบันไม่ได้อยู่ในช่วง ต้องตรงกับค่าข้อมูลที่เซ็นชื่อmaxSDK
(uint32) - ค่าที่ซ้ำกันของ maxSDK ในส่วนข้อมูลที่เซ็นชื่อ - ใช้เพื่อข้ามการยืนยันลายเซ็นนี้หากแพลตฟอร์มปัจจุบันไม่อยู่ในช่วง ต้องตรงกับค่าข้อมูลที่เซ็นชื่อ- ลำดับที่มีความยาวนำหน้าของ
signatures
ที่มีความยาวนำหน้า ดังนี้signature algorithm ID
(uint32)signature
ที่มีความยาวนำหน้า เหนือsigned data
public key
ที่มีความยาวนำหน้า (SubjectPublicKeyInfo, รูปแบบ ASN.1 DER)
โครงสร้าง proof-of-rotation และ self-trusted-old-certs
โครงสร้างหลักฐานการเปลี่ยนทำให้แอปเปลี่ยนใบรับรองการรับรองได้โดยไม่ถูกบล็อกในแอปอื่นๆ ที่แอปสื่อสารด้วย ลายเซ็นแอปจึงมีข้อมูลใหม่ 2 รายการดังต่อไปนี้
- การยืนยันให้บุคคลที่สามทราบว่าสามารถเชื่อถือใบรับรองการรับรองของแอปได้ไม่ว่าจะเชื่อถือใบรับรองก่อนหน้าของแอปหรือไม่
- ใบรับรองการรับรองแอปเวอร์ชันเก่าที่แอปยังคงเชื่อถือ
แอตทริบิวต์ proof-of-rotation ในส่วน signed-data ประกอบด้วยลิสต์แบบลิงก์เดี่ยว โดยแต่ละโหนดจะมีใบรับรองการรับรองที่ใช้ลงนามแอปเวอร์ชันก่อนหน้า แอตทริบิวต์นี้มีไว้เพื่อเก็บโครงสร้างข้อมูล proof-of-rotation และ self-trusted-old-certs เชิงแนวคิด รายการจะเรียงตามเวอร์ชันที่มีใบรับรองการรับรองที่เก่าที่สุดซึ่งสอดคล้องกับโหนดรูท โครงสร้างข้อมูลการพิสูจน์การหมุนเวียนสร้างขึ้นโดยให้ใบรับรองในแต่ละโหนดลงนามในรายการถัดไป ดังนั้นจึงมีการฝังหลักฐานไว้ในคีย์ใหม่แต่ละรายการว่าควรเชื่อถือได้เท่ากับคีย์เก่า
โครงสร้างข้อมูล self-trusted-old-certs สร้างขึ้นโดยการเพิ่ม Flag ไปยังโหนดแต่ละโหนดเพื่อระบุการเป็นสมาชิกและพร็อพเพอร์ตี้ของโหนดนั้นในชุด เช่น ธงอาจปรากฏขึ้นเพื่อระบุว่าใบรับรองการรับรองที่โหนดหนึ่งๆ เชื่อถือได้สำหรับการรับสิทธิ์การรับรอง Android Flag นี้ช่วยให้แอปอื่นๆ ที่ลงนามด้วยใบรับรองเก่ายังคงได้รับสิทธิ์การรับรองที่กําหนดโดยแอปที่ลงนามด้วยใบรับรองการรับรองใหม่ เนื่องจากแอตทริบิวต์พิสูจน์การหมุนเวียนทั้งหมดอยู่ในส่วนข้อมูลที่ลงนามของช่อง v3
signer
จึงได้รับการปกป้องโดยคีย์ที่ใช้ลงนามใน APK ที่มี
รูปแบบนี้ไม่อนุญาตให้มีคีย์การรับรองหลายรายการ และการรวมใบรับรองการรับรองต้นทางที่แตกต่างกันเข้าด้วยกัน (โหนดเริ่มต้นหลายโหนดไปยังที่เก็บข้อมูลทั่วไป)
รูปแบบ
การพิสูจน์การหมุนเวียนจะจัดเก็บไว้ในบล็อก APK Signature Scheme v3 ภายใต้รหัส 0x3ba06f8c
รูปแบบของไฟล์คือ
- ลำดับที่มีความยาวนำหน้าของ
levels
ที่มีความยาวนำหน้า ดังนี้signed data
ที่มีความยาวนำหน้า (ตามใบรับรองก่อนหน้า หากมี)- X.509
certificate
ที่มีความยาวนำหน้า (รูปแบบ ASN.1 DER) signature algorithm ID
(uint32) - อัลกอริทึมที่ใบรับรองใช้ในระดับก่อนหน้า
- X.509
flags
(uint32) - แฟล็กที่ระบุว่าใบรับรองนี้ควรอยู่ในโครงสร้าง self-trusted-old-certs หรือไม่ และสำหรับการดำเนินการใดsignature algorithm ID
(uint32) - ต้องตรงกับค่าจากส่วนข้อมูลที่เซ็นชื่อในระดับถัดไปsignature
ที่มีความยาวนำหน้ามากกว่าsigned data
ข้างต้น
ใบรับรองหลายรายการ
ระบบไม่รองรับผู้ลงนามหลายคน และ Google Play จะไม่เผยแพร่แอปที่ลงนามด้วยใบรับรองหลายรายการ
การยืนยัน
ใน Android 9 ขึ้นไป คุณสามารถยืนยัน APK ตาม APK Signature Scheme v3, v2 หรือ v1 แพลตฟอร์มเก่าๆ จะละเว้นลายเซ็น v3 และพยายามยืนยันลายเซ็น v2 ตามด้วย v1
รูปที่ 1 กระบวนการยืนยันลายเซ็น APK
การยืนยัน APK Signature Scheme v3
- ค้นหาบล็อกการรับรอง APK และตรวจสอบสิ่งต่อไปนี้
- ช่องขนาด 2 ช่องของบล็อกการรับรอง APK มีค่าเดียวกัน
- ไดเรกทอรีส่วนกลางของ ZIP ตามด้วยระเบียน "สิ้นสุดไดเรกทอรีส่วนกลาง" ของ ZIP
- ไม่มีการติดตามข้อมูลเพิ่มเติมต่อจาก End of Central Directory ของ ZIP
- ค้นหาบล็อก APK Signature Scheme v3 แรกภายในบล็อกการรับรอง APK หากมีบล็อก v3 ให้ไปยังขั้นตอนที่ 3 มิฉะนั้น ให้กลับไปยืนยัน APK โดยใช้รูปแบบ v2
- สําหรับ
signer
แต่ละรายการในบล็อก Signature Scheme v3 ของ APK ที่มีเวอร์ชัน SDK ขั้นต่ำและสูงสุดซึ่งอยู่ในช่วงของแพลตฟอร์มปัจจุบัน ให้ทําดังนี้- เลือก
signature algorithm ID
ที่แรงที่สุดที่รองรับจากsignatures
ลำดับความแรงขึ้นอยู่กับแต่ละเวอร์ชันการใช้งาน/แพลตฟอร์ม - ยืนยัน
signature
ที่เกี่ยวข้องจากsignatures
กับsigned data
โดยใช้public key
(ตอนนี้คุณแยกวิเคราะห์signed data
ได้แล้ว) - ตรวจสอบว่าเวอร์ชัน SDK ขั้นต่ำและสูงสุดในข้อมูลที่เซ็นสัญญาตรงกับเวอร์ชันที่ระบุสำหรับ
signer
- ตรวจสอบว่ารายการรหัสอัลกอริทึมลายเซ็นที่จัดเรียงใน
digests
และsignatures
เหมือนกัน (การดำเนินการนี้มีไว้เพื่อป้องกันการลบ/เพิ่มลายเซ็น) - คํานวณข้อมูลสรุปของเนื้อหา APK โดยใช้อัลกอริทึมข้อมูลสรุปเดียวกับอัลกอริทึมข้อมูลสรุปที่อัลกอริทึมการรับรองใช้
- ยืนยันว่าข้อมูลสรุปที่คำนวณได้ตรงกับ
digest
ที่เกี่ยวข้องจากdigests
- ตรวจสอบว่า SubjectPublicKeyInfo ของ
certificate
แรกในcertificates
เหมือนกับpublic key
- หากมีแอตทริบิวต์ proof-of-rotation สำหรับ
signer
ให้ตรวจสอบว่าโครงสร้างถูกต้องและsigner
นี้เป็นใบรับรองสุดท้ายในรายการ
- เลือก
- การยืนยันจะสำเร็จหากพบ
signer
เพียงรายการเดียวในช่วงของแพลตฟอร์มปัจจุบัน และขั้นตอนที่ 3 สำเร็จสำหรับsigner
รายการนั้น
การตรวจสอบความถูกต้อง
หากต้องการทดสอบว่าอุปกรณ์รองรับ v3 อย่างถูกต้อง ให้เรียกใช้PkgInstallSignatureVerificationTest.java
การทดสอบ CTS ใน cts/hostsidetests/appsecurity/src/android/appsecurity/cts/