Google is committed to advancing racial equity for Black communities. See how.
Эта страница была переведа с помощью Cloud Translation API.
Switch to English

Схема подписи APK v2

Схема подписи APK v2 - это схема подписи всего файла, которая увеличивает скорость проверки и усиливает гарантии целостности за счет обнаружения любых изменений в защищенных частях APK.

При подписании с использованием схемы подписи APK v2 блок подписи APK вставляется в файл APK непосредственно перед разделом центрального каталога ZIP. Внутри блока подписи APK подписи v2 и идентификационная информация подписывающего лица хранятся в блоке схемы подписи APK v2 .

APK до и после подписания

Рисунок 1. APK до и после подписания

Схема подписи APK v2 была представлена ​​в Android 7.0 (Nougat). Чтобы APK можно было установить на Android 6.0 (Marshmallow) и более старых устройствах, APK необходимо подписать с помощью подписи JAR, прежде чем подписывать по схеме v2.

Блокировка подписи APK

Для обеспечения обратной совместимости с форматом APK v1 подписи APK v2 и более новые хранятся в блоке подписи APK, новом контейнере, представленном для поддержки схемы подписи APK v2. В файле APK блок подписи APK расположен непосредственно перед центральным каталогом ZIP, который находится в конце файла.

Блок содержит пары ID-значение, упакованные таким образом, чтобы упростить поиск блока в APK. Подпись v2 APK хранится как пара ID-значение с ID 0x7109871a.

Формат

Формат блока подписи APK следующий (все числовые поля с прямым порядком байтов):

  • size of block в байтах (без учета этого поля) (uint64)
  • Последовательность пар ID-значение с префиксом длины uint64:
    • ID (uint32)
    • value (переменная длина: длина пары - 4 байта)
  • size of block в байтах - такой же, как и в самом первом поле (uint64)
  • magic «APK Sig Block 42» (16 байт)

APK анализируется путем поиска начала центрального каталога ZIP (путем нахождения записи конца центрального каталога ZIP в конце файла, а затем считывания начального смещения центрального каталога из записи). magic значение обеспечивает быстрый способ установить, что то, что предшествует Central Directory, скорее всего, является блоком подписи APK. Тогда size of block значения size of block фактически указывает на начало блока в файле.

Пары ID-значение с неизвестными ID следует игнорировать при интерпретации блока.

Схема подписи APK v2 Block

APK подписан одним или несколькими подписывающими лицами / лицами, каждое из которых представлено ключом подписи. Эта информация хранится в виде блока схемы подписи APK v2. Для каждой подписывающей стороны сохраняется следующая информация:

  • (алгоритм подписи, дайджест, подпись) кортежи. Дайджест сохраняется, чтобы отделить проверку подписи от проверки целостности содержимого APK.
  • Цепочка сертификатов X.509, представляющая личность подписавшего.
  • Дополнительные атрибуты в виде пар "ключ-значение".

Для каждого подписавшего APK проверяется с помощью поддерживаемой подписи из предоставленного списка. Подписи с неизвестным алгоритмом подписи игнорируются. Каждая реализация должна выбрать, какую подпись использовать, когда встречается несколько поддерживаемых подписей. Это позволит в будущем ввести более надежные методы подписи с обратной совместимостью. Предлагаемый подход заключается в проверке самой сильной подписи.

Формат

Блок схемы подписи APK v2 хранится внутри блока 0x7109871a APK под идентификатором 0x7109871a .

Формат блока схемы подписи APK v2 следующий (все числовые значения являются прямым порядком байтов, все поля с префиксом длины используют для длины uint32):

  • последовательность с префиксом длины signer префиксом длины:
    • signed data префиксом длины:
      • Последовательность digests префиксом длины:
      • последовательность certificates X.509 с префиксом длины:
        • certificate X.509 с префиксом длины (форма ASN.1 DER)
      • Последовательность additional attributes префиксом длины:
        • ID (uint32)
        • value (переменная длина: длина дополнительного атрибута - 4 байта)
    • Последовательность signatures префиксом длины:
      • signature algorithm ID (uint32)
      • signature префиксом длины поверх signed data
    • public key префиксом длины (SubjectPublicKeyInfo, форма DER ASN.1)

Идентификаторы алгоритмов подписи

  • 0x0101 - RSASSA-PSS с дайджестом SHA2-256, SHA2-256 MGF1, 32 байта соли, трейлер: 0xbc
  • 0x0102 - RSASSA-PSS с дайджестом SHA2-512, SHA2-512 MGF1, 64 байта соли, трейлер: 0xbc
  • 0x0103 - RSASSA-PKCS1-v1_5 с дайджестом SHA2-256. Это для систем сборки, требующих детерминированных подписей.
  • 0x0104 - RSASSA-PKCS1-v1_5 с дайджестом SHA2-512. Это для систем сборки, требующих детерминированных подписей.
  • 0x0201 - ECDSA с дайджестом SHA2-256
  • 0x0202 - ECDSA с дайджестом SHA2-512
  • 0x0301 - DSA с дайджестом SHA2-256

Все вышеперечисленные алгоритмы подписи поддерживаются платформой Android. Инструменты подписи могут поддерживать подмножество алгоритмов.

Поддерживаемые размеры ключей и кривые EC:

  • RSA: 1024, 2048, 4096, 8192, 16384
  • ЕС: NIST P-256, P-384, P-521
  • DSA: 1024, 2048, 3072

Контент с защитой целостности

В целях защиты содержимого APK файл APK состоит из четырех разделов:

  1. Содержимое записей ZIP (от смещения 0 до начала блока подписи APK)
  2. Блокировка подписи APK
  3. Центральный каталог ZIP
  4. ZIP Конец центрального каталога

Разделы APK после подписания

Рисунок 2. Разделы APK после подписания

Схема подписи APK v2 защищает целостность разделов 1, 3, 4 и signed data блоков signed data блока схемы подписи APK v2, содержащегося в разделе 2.

Целостность разделов 1, 3 и 4 защищена одним или несколькими дайджестами их содержимого, хранящимися в signed data блоках signed data которые, в свою очередь, защищены одной или несколькими подписями.

Дайджест по разделам 1, 3 и 4 вычисляется следующим образом, аналогично двухуровневому дереву Меркла . Каждый раздел разбивается на последовательные блоки размером 1 МБ (2 20 байтов). Последний кусок в каждом разделе может быть короче. Дайджест каждого фрагмента вычисляется 0xa5 объединения байта 0xa5 , длины фрагмента в байтах (с прямым порядком байтов uint32) и содержимого фрагмента. Дайджест верхнего уровня вычисляется 0x5a объединения байта 0x5a , количества блоков (с прямым порядком байтов uint32) и объединения дайджестов блоков в порядке их появления в APK. Дайджест вычисляется по частям, чтобы ускорить вычисление за счет его распараллеливания.

Дайджест APK

Рисунок 3. Дайджест APK

Защита раздела 4 (ZIP End of Central Directory) осложняется разделом, содержащим смещение ZIP Central Directory. Смещение изменяется при изменении размера блока подписи APK, например, при добавлении новой подписи. Таким образом, при вычислении дайджеста над концом ZIP центрального каталога поле, содержащее смещение центрального каталога ZIP, должно рассматриваться как содержащее смещение блока подписи APK.

Защита от отката

Злоумышленник может попытаться проверить APK с подписью v2 как APK с подписью v1 на платформах Android, которые поддерживают проверку APK с подписью v2. Чтобы предотвратить эту атаку, APK-файлы, подписанные v2, которые также подписаны v1, должны содержать атрибут X-Android-APK-Signed в основном разделе их файлов META-INF / *. SF. Значение атрибута - это разделенный запятыми набор идентификаторов схем подписи APK (идентификатор этой схемы - 2). При проверке подписи v1 верификатор APK должен отклонять APK, которые не имеют подписи для схемы подписи APK, которую верификатор предпочитает из этого набора (например, схема v2). Эта защита основана на том, что содержимое файлов META-INF / *. SF защищено подписями v1. См. Раздел о проверке APK с подписью JAR .

Злоумышленник может попытаться удалить более сильные подписи из блока схемы подписи APK v2. Чтобы смягчить эту атаку, список идентификаторов алгоритмов подписи, с которыми подписывался APK, сохраняется в signed data блоке signed data который защищен каждой подписью.

Проверка

В Android 7.0 и более поздних версиях APK-файлы можно проверять в соответствии со схемой подписи APK v2 + или подписью JAR (схема v1). Старые платформы игнорируют подписи v2 и проверяют только подписи v1.

Процесс проверки подписи APK

Рисунок 4. Процесс проверки подписи APK (новые шаги выделены красным цветом)

Проверка схемы подписи APK v2

  1. Найдите блок подписи APK и убедитесь, что:
    1. Два поля размера блока подписи APK содержат одно и то же значение.
    2. За центральным каталогом ZIP сразу следует запись ZIP End of Central Directory.
    3. ZIP Конец центрального каталога не сопровождается дополнительными данными.
  2. Найдите первый блок схемы подписи APK v2 внутри блока подписи APK. Если блок v2 присутствует, перейдите к шагу 3. В противном случае вернитесь к проверке APK с использованием схемы v1 .
  3. Для каждого signer в блоке схемы подписи APK v2:
    1. Выберите наиболее надежный поддерживаемый signature algorithm ID signatures из signatures . Порядок прочности зависит от каждой реализации / версии платформы.
    2. Проверьте соответствующую signature от signatures к signed data с помощью public key . (Теперь можно безопасно анализировать signed data .)
    3. Убедитесь, что упорядоченный список идентификаторов алгоритмов подписи в digests и signatures идентичен. (Это необходимо для предотвращения удаления / добавления подписи.)
    4. Вычислить дайджест содержимого APK, используя тот же алгоритм дайджеста, что и алгоритм дайджеста, используемый алгоритмом подписи.
    5. Убедитесь, что вычисленный дайджест идентичен соответствующему digest из digests .
    6. Убедитесь, что SubjectPublicKeyInfo первого certificate certificates совпадает с public key .
  4. Проверка считается успешной, если был найден хотя бы один signer и шаг 3 для каждого найденного signer .

Примечание . APK не следует проверять по схеме v1, если на шаге 3 или 4 произошел сбой.

Проверка APK-файла с подписью JAR (схема v1)

Подписанный JAR APK - это стандартный подписанный JAR , который должен содержать в точности записи, перечисленные в META-INF / MANIFEST.MF, и где все записи должны быть подписаны одним и тем же набором подписывающих лиц. Его целостность проверяется следующим образом:

  1. Каждая подписывающая сторона представлена ​​записями JAR META-INF / <signer> .SF и META-INF / <signer>. (RSA | DSA | EC).
  2. <signer>. (RSA | DSA | EC) - это PKCS # 7 CMS ContentInfo со структурой SignedData , подпись которой проверяется с помощью файла <signer> .SF.
  3. Файл <signer> .SF содержит дайджест всего файла META-INF / MANIFEST.MF и дайджесты каждого раздела META-INF / MANIFEST.MF. Полный дайджест файла MANIFEST.MF проверяется. Если это не удается, вместо этого проверяется дайджест каждого раздела MANIFEST.MF.
  4. META-INF / MANIFEST.MF содержит для каждой записи JAR с защитой целостности секцию с соответствующим именем, содержащую дайджест несжатого содержимого записи. Все эти дайджесты проверены.
  5. Проверка APK не выполняется, если APK содержит записи JAR, которые не указаны в MANIFEST.MF и не являются частью подписи JAR.

Таким образом, цепочка защиты - это <signer>. (RSA | DSA | EC) -> <signer> .SF -> MANIFEST.MF -> содержимое каждой записи JAR с защитой целостности.