APK Signature Scheme v3

Android: 9 รองรับ เอพีเคหมุนที่สำคัญ ซึ่งจะช่วยให้ปพลิเคชันสามารถในการเปลี่ยนที่สำคัญการลงนามของพวกเขาเป็นส่วนหนึ่งของการปรับปรุงเอพีเค เพื่อให้การหมุนเวียนเป็นไปได้จริง APK ต้องระบุระดับความน่าเชื่อถือระหว่างคีย์การลงนามใหม่และเก่า เพื่อสนับสนุนการหมุนที่สำคัญเราปรับปรุง รูปแบบลายเซ็นเอพีเค จาก v2 v3 เพื่อที่จะอนุญาตให้คีย์ทั้งเก่าและใหม่ที่จะนำมาใช้ V3 เพิ่มข้อมูลเกี่ยวกับเวอร์ชัน SDK ที่รองรับและโครงสร้างการพิสูจน์การหมุนไปยังบล็อกการลงนาม APK

บล็อกการลงชื่อ APK

เพื่อรักษาความเข้ากันได้แบบย้อนหลังกับรูปแบบ APK v1 ลายเซ็น APK v2 และ v3 จะถูกเก็บไว้ใน APK Signing Block ซึ่งอยู่ตรงหน้า ZIP Central Directory

APK ที่ v3 ลงนามในรูปแบบที่ถูกบล็อกเป็น เช่นเดียวกับ v2 ลายเซ็น v3 ของ APK ถูกจัดเก็บเป็นคู่ค่า ID ที่มี ID 0xf05368c0

APK Signature Scheme v3 Block

โครงการ v3 ที่ถูกออกแบบมาให้คล้ายกับ โครงการ v2 มันมีรูปแบบทั่วไปที่เหมือนกันและสนับสนุนเดียวกัน ลายเซ็นรหัสอัลกอริทึม ขนาดที่สำคัญและเส้นโค้ง EC

อย่างไรก็ตาม โครงร่าง v3 จะเพิ่มข้อมูลเกี่ยวกับเวอร์ชัน SDK ที่รองรับและโครงสร้างการพิสูจน์การหมุน

รูปแบบ

เอพีเคลายเซ็นโครงการ v3 บล็อกที่เก็บไว้ภายในเอพีเคลงนามบล็อกภายใต้รหัส 0xf05368c0

รูปแบบของ APK Signature Scheme v3 Block เป็นไปตามรูปแบบ v2:

  • ลำดับความยาวนำหน้าของความยาวนำหน้า signer :
    • ความยาวนำหน้า signed data :
      • ลำดับความยาวนำหน้าของความยาวนำหน้า digests :
        • signature algorithm ID (4 bytes)
        • digest (ความยาวนำหน้า)
      • ลำดับความยาวนำหน้าของ X.509 certificates :
        • ความยาวนำหน้า X.509 certificate (แบบ DER ASN.1)
      • minSDK (uint32) - ลงนามนี้ควรจะละเว้นถ้าแพลตฟอร์มรุ่นต่ำกว่าตัวเลขนี้
      • maxSDK (uint32) - ลงนามนี้ควรจะละเว้นถ้าแพลตฟอร์มรุ่นอยู่เหนือหมายเลขนี้
      • ลำดับความยาวนำหน้าของความยาวนำหน้า additional attributes :
        • ID (uint32)
        • value (ตัวแปรความยาว: ความยาวของแอตทริบิวต์เพิ่มเติม - 4 ไบต์)
        • ID - 0x3ba06f8c
        • value - หลักฐานของการหมุน struct
    • minSDK (uint32) - ที่ซ้ำกันของค่า minSDK ในส่วนของข้อมูลการลงนาม - ใช้ในการข้ามการตรวจสอบลายเซ็นนี้ถ้าแพลตฟอร์มปัจจุบันไม่ได้อยู่ในช่วง ต้องตรงกับค่าข้อมูลที่ลงนาม
    • maxSDK (uint32) - ที่ซ้ำกันของมูลค่า maxSDK ในส่วนของข้อมูลการลงนาม - ใช้ในการข้ามการตรวจสอบลายเซ็นนี้ถ้าแพลตฟอร์มปัจจุบันไม่ได้อยู่ในช่วง ต้องตรงกับค่าข้อมูลที่ลงนาม
    • ลำดับความยาวนำหน้าของความยาวนำหน้า signatures :
      • signature algorithm ID (uint32)
      • ความยาวนำหน้า signature กว่า signed data
    • ความยาวนำ public key (SubjectPublicKeyInfo, ASN.1 รูปแบบ DER)

หลักฐานการหมุนเวียนและโครงสร้างใบรับรองเก่าที่เชื่อถือได้

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

  • การยืนยันสำหรับบุคคลที่สามว่าใบรับรองการลงนามของแอปสามารถเชื่อถือได้ไม่ว่ารุ่นก่อนจะเชื่อถือได้
  • ใบรับรองการเซ็นชื่อเก่าของแอพซึ่งตัวแอพเองยังคงไว้วางใจ

แอตทริบิวต์ proof-of-rotation ในส่วนข้อมูลที่มีการลงนามประกอบด้วยรายการที่เชื่อมโยงโดยลำพัง โดยแต่ละโหนดมีใบรับรองการลงนามที่ใช้เพื่อลงนามแอปเวอร์ชันก่อนหน้า คุณลักษณะนี้มีขึ้นเพื่อให้มีโครงสร้างข้อมูลการพิสูจน์การหมุนเวียนของแนวคิดและโครงสร้างข้อมูลใบรับรองเก่าที่เชื่อถือได้ในตนเอง รายการเรียงลำดับตามเวอร์ชันที่มีใบรับรองการลงนามที่เก่าที่สุดที่สอดคล้องกับโหนดรูท โครงสร้างข้อมูลการพิสูจน์การหมุนถูกสร้างขึ้นโดยให้ใบรับรองในแต่ละโหนดลงนามในรายการถัดไป และทำให้คีย์ใหม่แต่ละอันมีหลักฐานว่าควรเชื่อถือได้เท่ากับคีย์ที่เก่ากว่า

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

นี้ติ๊ดรูปแบบ ปุ่มลงนามหลาย และการบรรจบกันของ ใบรับรองการลงนามบรรพบุรุษที่แตกต่างกัน ให้เป็นหนึ่ง (โหนดเริ่มต้นหลายที่อ่างล้างจานธรรมดา)

รูปแบบ

หลักฐานของการหมุนจะถูกเก็บไว้ภายในเอพีเคลายเซ็นโครงการ v3 บล็อกภายใต้รหัส 0x3ba06f8c รูปแบบของมันคือ:

  • ลำดับความยาวนำหน้าของความยาวนำหน้า levels :
    • ความยาวนำ signed data (โดยใบรับรองก่อนหน้านี้ - ถ้ามี)
      • ความยาวนำหน้า X.509 certificate (แบบ DER ASN.1)
      • signature algorithm ID (uint32) - อัลกอริทึมที่ใช้โดยใบรับรองในระดับก่อนหน้า
    • flags (uint32) - ธงแสดงให้เห็นหรือไม่ว่าใบรับรองนี้ควรจะอยู่ในตัวเองที่เชื่อถือเก่าใบรับรอง-struct และที่การดำเนินงาน
    • signature algorithm ID (uint32) - ต้องตรงกับหนึ่งจากส่วนข้อมูลที่ได้ลงนามในระดับต่อไป
    • ความยาวนำหน้า signature กว่าข้างต้น signed data

ใบรับรองหลายใบ

ปัจจุบัน Android ปฏิบัติต่อ APK ที่ลงนามด้วยใบรับรองหลายฉบับโดยมีข้อมูลระบุตัวตนการลงนามที่ไม่ซ้ำกันซึ่งแยกจากใบรับรองที่ประกอบด้วย ดังนั้น แอตทริบิวต์การพิสูจน์การหมุนเวียนในส่วนข้อมูลที่มีการลงนามจะสร้างกราฟ acyclic ที่กำหนดทิศทาง ซึ่งสามารถมองได้ดีกว่าว่าเป็นรายการที่เชื่อมโยงโดยลำพัง โดยแต่ละชุดของผู้ลงนามสำหรับเวอร์ชันที่กำหนดจะเป็นตัวแทนของโหนดเดียว สิ่งนี้จะเพิ่มความซับซ้อนเป็นพิเศษให้กับโครงสร้างการพิสูจน์การหมุน (เวอร์ชันผู้ลงนามหลายคนด้านล่าง) โดยเฉพาะอย่างยิ่ง การสั่งซื้อกลายเป็นเรื่องที่น่ากังวล ยิ่งไปกว่านั้น เป็นไปไม่ได้ที่จะลงนาม APK อย่างอิสระอีกต่อไป เนื่องจากโครงสร้างการพิสูจน์การหมุนเวียนต้องมีใบรับรองการลงนามแบบเก่าที่ลงนามในใบรับรองชุดใหม่ แทนที่จะลงนามทีละรายการ ตัวอย่างเช่น APK ที่ลงนามโดยคีย์ A ซึ่งประสงค์จะลงนามโดยคีย์ใหม่สองคีย์ B และ C ไม่สามารถมีผู้ลงนาม B เพียงแค่รวมลายเซ็นโดย A หรือ B เนื่องจากเป็นข้อมูลประจำตัวการลงนามที่แตกต่างจาก B และ C ซึ่งจะ หมายความว่าผู้ลงนามต้องประสานงานก่อนสร้างโครงสร้างดังกล่าว

แอตทริบิวต์การพิสูจน์การหมุนเวียนของผู้ลงนามหลายคน

  • ลำดับความยาวนำหน้าของความยาวนำหน้า sets :
    • signed data (โดยชุดก่อนหน้านี้ - ถ้ามี)
      • ลำดับความยาวนำหน้าของ certificates
        • ความยาวนำหน้า X.509 certificate (แบบ DER ASN.1)
      • ลำดับของ signature algorithm IDs (uint32) - หนึ่งสำหรับแต่ละใบรับรองจากชุดก่อนหน้านี้ในลำดับเดียวกัน
    • flags (uint32) - ธงแสดงให้เห็นหรือไม่ว่าชุดของใบรับรองนี้ควรจะอยู่ในตัวเองที่เชื่อถือเก่าใบรับรอง-struct และที่การดำเนินงาน
    • ลำดับความยาวนำหน้าของความยาวนำหน้า signatures :
      • signature algorithm ID (uint32) - ต้องตรงกับหนึ่งจากส่วนข้อมูลที่ได้ลงนามใน
      • ความยาวนำหน้า signature กว่าข้างต้น signed data

บรรพบุรุษหลายคนในโครงสร้างการพิสูจน์การหมุน

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

การยืนยัน

ใน Android 9 ขึ้นไป สามารถตรวจสอบ APK ได้ตามแผน APK Signature Scheme v3, v2 หรือ v1 แพลตฟอร์มเก่าละเว้นลายเซ็น v3 และพยายามตรวจสอบลายเซ็น v2 จากนั้น v1

ขั้นตอนการตรวจสอบลายเซ็น APK

รูปที่ 1 เอพีเคกระบวนการตรวจสอบลายเซ็น

APK Signature Scheme v3 การตรวจสอบ

  1. ค้นหา APK Signing Block และตรวจสอบว่า:
    1. ฟิลด์ขนาดสองช่องของ APK Signing Block มีค่าเท่ากัน
    2. ZIP Central Directory ตามด้วย ZIP End of Central Directory ทันที
    3. ZIP End of Central Directory ไม่ได้ตามด้วยข้อมูลเพิ่มเติม
  2. ค้นหา APK Signature Scheme v3 Block แรกภายใน APK Signing Block หาก v3 บล็อกเป็นปัจจุบันดำเนินการต่อไปขั้นตอนที่ 3 มิฉะนั้นถอยกลับไปตรวจสอบเอพีเค ใช้รูปแบบ v2
  3. สำหรับแต่ละ signer ในลายเซ็นเอพีเคโครงการ v3 บล็อกกับนาทีและรุ่น SDK สูงสุดที่อยู่ในช่วงของแพลตฟอร์มปัจจุบัน:
    1. เลือกที่แข็งแกร่งสนับสนุน signature algorithm ID จาก signatures ลำดับความแรงนั้นขึ้นอยู่กับการใช้งาน/เวอร์ชันของแพลตฟอร์มแต่ละเวอร์ชัน
    2. ตรวจสอบที่สอดคล้องกัน signature จาก signatures กับ signed data โดยใช้ public key (ตอนนี้มันเป็นความปลอดภัยที่จะแยก signed data .)
    3. ตรวจสอบนาทีและ SDK รุ่นสูงสุดในข้อมูลเซ็นตรงกับที่ระบุไว้สำหรับ signer
    4. ตรวจสอบว่ารายการสั่งซื้อรหัสอัลกอริทึมลายเซ็นในการ digests และ signatures เป็นเหมือนกัน (เพื่อป้องกันการลอก/เพิ่มลายเซ็น)
    5. คำนวณย่อยของเนื้อหาเอพีเค โดยใช้ขั้นตอนวิธีการเดียวกันย่อยเป็นย่อยอัลกอริทึมที่ใช้โดยอัลกอริทึมลายเซ็น
    6. ตรวจสอบว่าการคำนวณแยกย่อยเป็นเหมือนที่สอดคล้อง digest จาก digests
    7. ตรวจสอบ SubjectPublicKeyInfo แรกที่ certificate ของ certificates เป็นเหมือน public key
    8. ถ้าหลักฐานของการหมุนแอตทริบิวต์ที่มีอยู่สำหรับ signer ยืนยันว่าโครงสร้างที่ถูกต้องและ signer เป็นใบรับรองสุดท้ายในรายการ
  4. ตรวจสอบถ้าประสบความสำเร็จตรงหนึ่ง signer พบว่าในช่วงของแพลตฟอร์มในปัจจุบันและในขั้นตอนที่ 3 ประสบความสำเร็จสำหรับการที่ signer

การตรวจสอบความถูกต้อง

การทดสอบที่สนับสนุนอุปกรณ์ของคุณถูกต้อง v3 รัน PkgInstallSignatureVerificationTest.java ทดสอบ CTS ใน cts/hostsidetests/appsecurity/src/android/appsecurity/cts/ /