O Google está comprometido em promover a equidade racial para as comunidades negras. Veja como.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

APK Esquema de assinatura v2

O Esquema de assinatura do APK v2 é um esquema de assinatura de arquivo inteiro que aumenta a velocidade de verificação e fortalece as garantias de integridade ao detectar quaisquer alterações nas partes protegidas do APK.

A assinatura usando o Esquema de assinatura APK v2 insere um bloco de assinatura APK no arquivo APK imediatamente antes da seção Diretório central do ZIP. Dentro do Bloco de assinatura do APK, as assinaturas v2 e as informações de identidade do assinante são armazenadas em um bloco do APK Signature Scheme v2 .

APK antes e depois da assinatura

Figura 1. APK antes e depois da assinatura

O APK Signature Scheme v2 foi introduzido no Android 7.0 (Nougat). Para tornar um APK instalável no Android 6.0 (Marshmallow) e em dispositivos mais antigos, o APK deve ser assinado usando a assinatura JAR antes de ser assinado com o esquema v2.

APK Bloco de assinatura

Para manter a compatibilidade com versões anteriores do formato APK v1, v2 e assinaturas APK mais recentes são armazenadas em um bloco de assinatura do APK, um novo contêiner introduzido para oferecer suporte ao Esquema de assinatura do APK v2. Em um arquivo APK, o bloco de assinatura do APK está localizado imediatamente antes do diretório central do ZIP, localizado no final do arquivo.

O bloco contém pares de valores de ID agrupados de maneira a facilitar a localização do bloco no APK. A assinatura v2 do APK é armazenada como um par de valor e ID com o ID 0x7109871a.

Formato

O formato do bloco de assinatura do APK é o seguinte (todos os campos numéricos são little-endian):

  • size of block em bytes (excluindo este campo) (uint64)
  • Sequência de pares de valor-ID com prefixo uint64 de comprimento:
    • ID (uint32)
    • value (comprimento variável: comprimento do par - 4 bytes)
  • size of block em bytes - o mesmo que o primeiro campo (uint64)
  • magic “APK Sig Block 42” (16 bytes)

O APK é analisado localizando primeiro o início do Diretório Central ZIP (localizando o registro Fim do Diretório ZIP no final do arquivo e lendo o deslocamento inicial do Diretório Central no registro). O valor magic fornece uma maneira rápida de estabelecer que o que precede o Diretório Central provavelmente é o Bloco de assinatura do APK. O size of block valor size of block aponta de maneira eficiente para o início do bloco no arquivo.

Pares de ID-valor com IDs desconhecidos devem ser ignorados ao interpretar o bloco.

APK Esquema de assinatura v2 Block

O APK é assinado por um ou mais assinantes / identidades, cada um representado por uma chave de assinatura. Essas informações são armazenadas como um bloco de esquema de assinatura APK v2. Para cada assinante, as seguintes informações são armazenadas:

  • (algoritmo de assinatura, resumo, assinatura) tuplas. O resumo é armazenado para dissociar a verificação da assinatura da verificação de integridade do conteúdo do APK.
  • Cadeia de certificados X.509 representando a identidade do assinante.
  • Atributos adicionais como pares de valor-chave.

Para cada assinante, o APK é verificado usando uma assinatura suportada da lista fornecida. Assinaturas com algoritmos de assinatura desconhecidos são ignoradas. Cabe a cada implementação escolher qual assinatura usar quando várias assinaturas suportadas forem encontradas. Isso permite a introdução de métodos de assinatura mais fortes no futuro de uma maneira compatível com versões anteriores. A abordagem sugerida é verificar a assinatura mais forte.

Formato

O bloco do esquema de assinatura do APK v2 é armazenado dentro do bloco de assinatura do APK com o ID 0x7109871a .

O formato do bloco APK Signature Scheme v2 é o seguinte (todos os valores numéricos são little-endian, todos os campos com prefixo de comprimento usam uint32 para comprimento):

  • sequência com prefixo de comprimento do signer prefixo de comprimento:
    • signed data prefixo de comprimento:
      • sequência com prefixo de comprimento dos digests prefixo de comprimento:
      • sequência prefixada em comprimento dos certificates X.509:
        • certificate X.509 com prefixo de comprimento (formulário ASN.1 DER)
      • sequência prefixada por comprimento de additional attributes prefixados por comprimento:
        • ID (uint32)
        • value (comprimento variável: comprimento do atributo adicional - 4 bytes)
    • sequência com prefixo de comprimento de signatures prefixo de comprimento:
      • signature algorithm ID (uint32)
      • signature prefixo de comprimento sobre signed data
    • public key prefixo de comprimento (SubjectPublicKeyInfo, formulário ASN.1 DER)

IDs do algoritmo de assinatura

  • 0x0101 - RSASSA-PSS com resumo SHA2-256, SHA2-256 MGF1, 32 bytes de sal, trailer: 0xbc
  • 0x0102 - RSASSA-PSS com resumo SHA2-512, SHA2-512 MGF1, 64 bytes de sal, trailer: 0xbc
  • 0x0103 - RSASSA-PKCS1-v1_5 com digestão SHA2-256. Isto é para sistemas de construção que requerem assinaturas determinísticas.
  • 0x0104 - RSASSA-PKCS1-v1_5 com resumo SHA2-512. Isto é para sistemas de construção que requerem assinaturas determinísticas.
  • 0x0201 - ECDSA com resumo SHA2-256
  • 0x0202 - ECDSA com resumo SHA2-512
  • 0x0301 - DSA com resumo SHA2-256

Todos os algoritmos de assinatura acima são suportados pela plataforma Android. As ferramentas de assinatura podem suportar um subconjunto dos algoritmos.

Tamanhos de teclas e curvas EC suportados:

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

Conteúdo protegido por integridade

Para proteger o conteúdo do APK, um APK consiste em quatro seções:

  1. Conteúdo das entradas ZIP (do deslocamento 0 até o início do APK Signing Block)
  2. APK Bloco de assinatura
  3. Diretório Central ZIP
  4. Fim ZIP do Diretório Central

Seções do APK após a assinatura

Figura 2. Seções do APK após a assinatura

O esquema de assinatura do APK v2 protege a integridade das seções 1, 3, 4 e os blocos de signed data bloco do esquema de assinatura do APK v2 contidos na seção 2.

A integridade das seções 1, 3 e 4 é protegida por um ou mais resumos de seu conteúdo armazenados em blocos de signed data que, por sua vez, são protegidos por uma ou mais assinaturas.

O resumo das seções 1, 3 e 4 é calculado da seguinte forma, semelhante a uma árvore Merkle de dois níveis. Cada seção é dividida em pedaços consecutivos de 1 MB (2 20 bytes). O último pedaço em cada seção pode ser mais curto. O resumo de cada parte é calculado sobre a concatenação do byte 0xa5 , o comprimento da parte em bytes (little-endian uint32) e o conteúdo da parte. O resumo de nível superior é calculado sobre a concatenação do byte 0x5a , o número de chunks (little-endian uint32) e a concatenação dos resumos dos chunks na ordem em que os chunks aparecem no APK. O resumo é calculado de forma fragmentada para permitir acelerar o cálculo paralelizando-o.

Resumo do APK

Figura 3. Resumo do APK

A proteção da seção 4 (final do diretório central do ZIP) é complicada pela seção que contém o deslocamento do diretório central do ZIP. O deslocamento muda quando o tamanho do bloco de assinatura do APK muda, por exemplo, quando uma nova assinatura é adicionada. Assim, ao computar o resumo sobre o ZIP End of Central Directory, o campo que contém o deslocamento do ZIP Central Directory deve ser tratado como o deslocamento do bloco de assinatura do APK.

Proteções de reversão

Um invasor pode tentar ter um APK assinado por v2 verificado como APK assinado em v1 nas plataformas Android compatíveis com a verificação do APK assinado com v2. Para atenuar esse ataque, os APKs com assinatura v2 e também com assinatura v1 devem conter um atributo X-Android-APK-Signed na seção principal de seus arquivos META-INF / *. SF. O valor do atributo é um conjunto separado por vírgula de IDs de esquema de assinatura APK (o ID deste esquema é 2). Ao verificar a assinatura v1, o verificador APK é necessário para rejeitar APKs que não possuem uma assinatura para o esquema de assinatura APK que o verificador prefere neste conjunto (por exemplo, esquema v2). Essa proteção depende do fato de que os arquivos META-INF / *. SF do conteúdo são protegidos por assinaturas v1. Consulte a seção sobre verificação do APK assinado por JAR .

Um invasor pode tentar retirar assinaturas mais fortes do bloco do APK Signature Scheme v2. Para atenuar esse ataque, a lista de IDs do algoritmo de assinatura com os quais o APK estava sendo assinado é armazenada no bloco de signed data protegido por cada assinatura.

Verificação

No Android 7.0 e posterior, os APKs podem ser verificados de acordo com o esquema de assinatura do APK v2 + ou assinatura JAR (esquema v1). Plataformas mais antigas ignoram assinaturas v2 e verificam apenas assinaturas v1.

Processo de verificação de assinatura do APK

Figura 4. Processo de verificação da assinatura do APK (novas etapas em vermelho)

Verificação do APK Signature Scheme v2

  1. Localize o bloco de assinatura do APK e verifique se:
    1. Dois campos de tamanho do APK Signing Block contêm o mesmo valor.
    2. O ZIP Central Directory é imediatamente seguido pelo registro ZIP End of Central Directory.
    3. ZIP O final do diretório central não é seguido por mais dados.
  2. Localize o primeiro bloco do APK Signature Scheme v2 dentro do bloco de assinatura do APK. Se o bloco v2, se houver, prossiga para a etapa 3. Caso contrário, volte a verificar o APK usando o esquema v1 .
  3. Para cada signer no APK Signature Scheme v2 Block:
    1. Escolha o signature algorithm ID do signature algorithm ID suportado mais forte entre signatures . A ordem de força depende de cada versão de implementação / plataforma.
    2. Verifique a signature correspondente de signatures signed data usando public key . (Agora é seguro analisar signed data .)
    3. Verifique se a lista ordenada de IDs do algoritmo de assinatura nos digests e signatures é idêntica. (Isso evita a remoção / adição de assinatura.)
    4. Calcule a compilação do conteúdo do APK usando o mesmo algoritmo de compilação usado pelo algoritmo de assinatura.
    5. Verifique se o resumo computado é idêntico ao digest correspondente dos digests .
    6. Verifique se SubjectPublicKeyInfo do primeiro certificate de certificates é idêntico à public key .
  4. A verificação é bem-sucedida se pelo menos um signer for encontrado e a etapa 3 for bem-sucedida para cada signer encontrado.

Nota : o APK não deve ser verificado usando o esquema v1 se ocorrer uma falha na etapa 3 ou 4.

Verificação do APK assinado por JAR (esquema v1)

O APK assinado por JAR é um JAR assinado padrão , que deve conter exatamente as entradas listadas em META-INF / MANIFEST.MF e onde todas as entradas devem ser assinadas pelo mesmo conjunto de assinantes. Sua integridade é verificada da seguinte maneira:

  1. Cada signatário é representado por uma entrada JAR META-INF / <signer> .SF e META-INF / <signer>. (RSA | DSA | EC).
  2. <signer>. (RSA | DSA | EC) é uma estrutura PKCS # 7 CMS ContentInfo com SignedData cuja assinatura é verificada no arquivo <signer> .SF.
  3. O arquivo <signer> .SF contém um resumo do arquivo META-INF / MANIFEST.MF e resumos de cada seção do META-INF / MANIFEST.MF. O resumo do arquivo MANIFEST.MF é verificado. Se isso falhar, o resumo de cada seção MANIFEST.MF é verificado.
  4. META-INF / MANIFEST.MF contém, para cada entrada JAR protegida por integridade, uma seção com nome correspondente que contém o resumo do conteúdo não compactado da entrada. Todos esses resumos são verificados.
  5. A verificação do APK falhará se o APK contiver entradas JAR que não estão listadas no MANIFEST.MF e não fazem parte da assinatura JAR.

A cadeia de proteção é, portanto, <signer>. (RSA | DSA | EC) -> <signer> .SF -> MANIFEST.MF -> conteúdo de cada entrada JAR protegida por integridade.