У меня короткий вопрос: что именно возвращает этот вызов?

context.getPackageManager().getPackageInfo(context.getPackageName(), GET_SIGNATURES).signatures[0].toByteArray();

Я знаю, что он возвращает первый сертификат приложения для приложения, который является CERT.RSA в папке META-INF, но что конкретно он возвращает? Просто байтовый массив, который представляет весь сертификат как файл или какой-то другой байтовый массив? Я мало что знаю о структуре сертификатов и данных, которые они содержат, поэтому понятия не имею.

Лучшим ответом будет инструкция для openssl, в которой я получаю возвращаемое значение из приведенной выше строки кода.

6
SkryptX 11 Май 2016 в 14:53

3 ответа

Лучший ответ

Я наконец-то проверил это сам на симуляторе Android и получил окончательный ответ. На самом деле это не сложно понять, когда я понял, что PKCS7 - это просто форма хранения или, скорее, контейнер для различных типов подписей.

В приложении

Вызов возвращает первую подпись в файле CERT.RSA. Это файл PKCS7, в который встроен сертификат X.509, и, судя по тому, что я читал, это всегда только одна подпись для приложений Android.

Signature sig = context.getPackageManager().getPackageInfo(context.getPackageName(), GET_SIGNATURES).signatures[0];

Этот Signature, полученный выше, можно напрямую использовать для создания работающего сертификата X.509, подобного этому (взято из здесь ):

 byte[] rawCert = sig.toByteArray();
 InputStream certStream = new ByteArrayInputStream(rawCert);

 CertificateFactory certFactory;
 X509Certificate x509Cert;
 try {
      certFactory = CertificateFactory.getInstance("X509");
      x509Cert = (X509Certificate) certFactory.generateCertificate(certStream);

      //do stuff with your certificate
 } catch(Exception ex) {
      //handle exception
 }

В другом месте

Если у вас есть сертификат вне вашего собственного приложения для Android, и вам нужен тот же поток байтов, который обеспечивается функцией выше, вы можете сделать то же самое с простой Java-программой, например:

 FileInputStream is = new FileInputStream("CERT.RSA");
 CertificateFactory cf = CertificateFactory.getInstance("X.509");
 X509Certificate c = (X509Certificate) cf.generateCertificates(is).toArray()[0];
 byte[] rawCert = c.getEncoded();

В другом месте

openssl

Этот код сначала читает файл, создает openssl, а затем выполняет важный шаг - изолировать первый сертификат в контейнере PKCS7. И затем {{X1}} наконец дает вам то же самое представление, что и описанный выше метод.

 openssl pkcs7 -inform DER -in CERT.RSA -print_certs -text

Это даст вам хороший обзор содержащейся информации, а в конце

 -----BEGIN CERTIFICATE-----
 ...
 -----END CERTIFICATE-----

Блок. Он содержит те же данные, что и выше. Если вы проанализируете содержимое этого блока и декодируете его с помощью base64, он даст вам тот же массив байтов, что и в двух верхних примерах.

0
Community 23 Май 2017 в 12:22
context.getPackageManager().getPackageInfo(context.getPackageName(), GET_SIGNATURES).signatures[0]

Вернет представление сертификата подписи, связанного с пакетом приложения. Это будет экземпляр класса Signature, как определено здесь в документация. (Название «Подпись» немного вводит в заблуждение и даже упоминается в самой документации).

context.getPackageManager().getPackageInfo(context.getPackageName(), GET_SIGNATURES).signatures[0].toByteArray();

Вернет его представление байтового массива. т.е. представление байтового массива файла сертификата.

Кроме того, сертификат - это не что иное, как текстовый файл, но данные структурированы в общий формат и закодированы. X.509 - один из наиболее широко используемых форматов. Вы можете найти его здесь. RFC для сертификата X.509 находится здесь. Сертификаты структурированы таким образом, что их можно легко проверить, если они были изменены третьей стороной.

Нет команды openssl, которая напрямую возвращает byte []. Ближайшее, что я мог придумать, - это команда openssl, которую вы можете использовать для получения текстового представления сертификата.

$ openssl x509 -in <your-certificate> -noout -text
0
Ruchira Randana 19 Май 2016 в 12:59

Элемент подписей PackageInfo - это просто массив всех подписей, считанных из файла пакета.

public Signature[] signatures;

Класс android.content.pm.Signature хранит подпись в форме

private final byte[] mSignature;

Вот что делает toByteArray ():

/**
 * @return the contents of this signature as a byte array.
 */
public byte[] toByteArray() {
    byte[] bytes = new byte[mSignature.length];
    System.arraycopy(mSignature, 0, bytes, 0, mSignature.length);
    return bytes;
}

По сути, этот код просто предоставляет вам массив байтов подписи, используемой для подписи пакета.

Предполагая, что CERT.RSA - это файл RSA в папке META-INF apk, вы можете получить подписи пакетов MD5, SHA1 и SHA256 через:

keytool -printcert -file CERT.RSA
0
Chebyr 25 Май 2016 в 11:33