Show Android Certificate

I have a short question: what causes this call?

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

I know that it returns the first application certificate for the application, which is CERT.RSA in the META-INF folder, but what returns it? Just a byte array that represents the entire certificate as a file or some other byte array? I do not really understand the structure of certificates and the data that they contain, so I really do not know.

The best answer would be an instruction for openssl so that I get the return value from the specified line of code.

+6
source share
3 answers

I finally tested it myself on an Android simulator and got the final answer. It’s actually not difficult to understand, as soon as I realized that PKCS7 is just a form of storage or, rather, a container for different types of signatures.

In the application

The call returns the first signature in the CERT.RSA file. This is a PKCS7 file that includes an X.509 certificate, and from what I read, it was always only one signature for Android apps.

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

This Signature , obtained from above, can be directly used to create an X.509 working certificate similar to this (taken from here ):

  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 } 

Anywhere

If you have a certificate outside of your own Android application and require the same byte stream provided by the function above, you can do the same with a simple Java program like this:

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

This code first reads the file, creates a CertificateFactory , and then an important step to isolate the first certificate in the PKCS7 container. And then c.getEncoded() finally gives you the same view as the method above.

Openssl

And last but not least, the openssl command for it (taken from here ):

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

This will give you a brief overview of the information contained at the end.

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

block. It contains the same data as above. If you parse the contents of this block and decode it with base64, it will give you the same byte array as in the top two examples.

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

Will return a view of the signature certificate associated with the application package. This will be an instance of the Signature class, as indicated in the documentation here . (The name "Signature" is a little misleading and is even mentioned in the documentation itself).

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

Would return a representation of the bytes of the array. i.e.: representation of the byte array of the certificate file.

Adding to this, the certificate is not something new than a text file, but the data is structured in a common format and encoded. X.509 is one of the most widely used formats. You can find it here . RFC for X.509 certificate here . Certificates are structured in such a way that they can be easily verified if modified by a third party.

There is no openssl command that directly returns byte []. The closest I could think of is the openssl command, which you can use to get the text representation of the certificate.

 $ openssl x509 -in <your-certificate> -noout -text 
0
source

The signatures PackageInfo element is just an array of all signatures read from the package file.

 public Signature[] signatures; 

The android.content.pm.Signature class saves the signature in the form

 private final byte[] mSignature; 

This is what toByteArray () does:

 /** * @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; } 

Thus, essentially, this code simply provides you with an array of bytes of the signature used to sign the package.

Assuming that CERT.RSA is an RSA file in the META-INF apk folder, you can get the MD5, SHA1, and SHA256 package signatures via:

 keytool -printcert -file CERT.RSA 
0
source

All Articles