Just An Application

August 16, 2014

And Another One: Part Sixteen — Spot The Deliberate Mistake

If you have made it this far through the labyrinth of method calls you will undoubtedly have noticed that at no point has there been any attempt made to determine whether the certificates that were included in the signed signature file and that were returned by the call to the JarUtils.createChain method actually have any relationship to one another, that is, whether the supposed issuer of each certificate did in fact sign that certificate.

It is not difficult to do so

There is a very helpful method on the class java.security.certificate.Certificate

    public abstract void verify(PublicKey key)
                         throws
                             CertificateException,
                             NoSuchAlgorithmException,
                             InvalidKeyException,
                             NoSuchProviderException,
                             SignatureException

which

Verifies that this certificate was signed using the private key that corresponds to the specified public key.

Verifying A Certificate Chain

This is a modified version of the original application which uses the java.security.certificate.Certificate verify method to verify its certificates as encapsulated in its signatures.


    package xper.android.app.saithe;
    
    import java.io.ByteArrayInputStream;
    import java.security.Principal;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.content.pm.Signature;
    import android.view.Menu;
    
    public class MainActivity
                 extends
                     Activity
    {
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            PackageManager pm = getPackageManager();
            
            try
            {
                PackageInfo pi = pm.getPackageInfo("xper.android.app.saithe", PackageManager.GET_SIGNATURES);
    
                boolean verified = verifyCertificates(pi.signatures);
    
                System.out.println("verified == " + verified);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu)
        {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }

        private boolean verifyCertificates(Signature[] theSignatures)
                        throws
                            Exception
        {
            X509Certificate[] certificates = makeCertificates(theSignatures);
        
            return verifyCertificates(certificates[0], certificates);
        }
        
        private boolean verifyCertificates(X509Certificate theSignerCertificate, X509Certificate[] theCertificates)
                        throws
                            Exception
        {
            X509Certificate current = theSignerCertificate;
		
            while (true)
            {
                System.out.println("current subject == " + current.getSubjectDN());
        
                Principal issuer = current.getIssuerDN();
        
                System.out.println("current issuer  == " + issuer);
        
                X509Certificate issuerCertificate = findCertificate(issuer, theCertificates);
        
                if (issuerCertificate == null)
                {
                    return false;
                }
                current.verify(issuerCertificate.getPublicKey());
                if (current.getSubjectDN().equals(issuer))
                {
                    return true;
                }
                current = issuerCertificate;
            }
        }
        
        private X509Certificate findCertificate(Principal theIssuer, X509Certificate[] theCertificates)
        {
            for (X509Certificate c : theCertificates)
            {
                if (c.getSubjectDN().equals(theIssuer))
                {
                    return c;
                }
            }
            return null;
        }
        
        private X509Certificate[] makeCertificates(Signature[] theSignatures)
                                  throws
                                      Exception
        {
            CertificateFactory cf            = CertificateFactory.getInstance("X.509");
            int                nCertificates = theSignatures.length;
            X509Certificate[]  certificates  = new X509Certificate[nCertificates];
		
            for (int i = 0; i < nCertificates; i++)
            {
                certificates[i] = (X509Certificate)cf.generateCertificate(
                                                          new ByteArrayInputStream(
                                                                  theSignatures[i].toByteArray()));
            }
            return certificates;
        }
    }

and this is what happens when you run it

    ...
    
    I/ActivityManager(  516): Start proc xper.android.app.saithe for activity xper.android.app.saithe/.MainActivity: pid=2296 uid=10077 gids={50077, 1028}
    D/dalvikvm( 2296): Late-enabling CheckJNI
    I/System.out( 2296): current subject == CN=AndroidApplication Saithe, OU=AndroidApplication Saithe Group, \
        O=ASH Two, L=Emerald City, ST=Erehwon, C=OZ
    I/System.out( 2296): current issuer  == CN=Adobe Systems Incorporated, OU=Information Systems,  \
        O=Adobe Systems Incorporated, L=San Jose, ST=California, C=US
    W/System.err( 2296): java.security.SignatureException: error:04091077:rsa routines:INT_RSA_VERIFY:wrong signature length
    W/System.err( 2296): 	at org.apache.harmony.xnet.provider.jsse.NativeCrypto.X509_verify(Native Method)
    W/System.err( 2296): 	at org.apache.harmony.xnet.provider.jsse.OpenSSLX509Certificate.verifyOpenSSL(OpenSSLX509Certificate.java:333)
    W/System.err( 2296): 	at org.apache.harmony.xnet.provider.jsse.OpenSSLX509Certificate.verify(OpenSSLX509Certificate.java:366)
    W/System.err( 2296): 	at xper.android.app.saithe.MainActivity.verifyCertificates(MainActivity.java:122)
    W/System.err( 2296): 	at xper.android.app.saithe.MainActivity.verifyCertificates(MainActivity.java:99)
    W/System.err( 2296): 	at xper.android.app.saithe.MainActivity.onCreate(MainActivity.java:40)
    W/System.err( 2296): 	at android.app.Activity.performCreate(Activity.java:5133)
    W/System.err( 2296): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
    W/System.err( 2296): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
    W/System.err( 2296): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
    W/System.err( 2296): 	at android.app.ActivityThread.access$600(ActivityThread.java:141)
    W/System.err( 2296): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
    W/System.err( 2296): 	at android.os.Handler.dispatchMessage(Handler.java:99)
    W/System.err( 2296): 	at android.os.Looper.loop(Looper.java:137)
    W/System.err( 2296): 	at android.app.ActivityThread.main(ActivityThread.java:5103)
    W/System.err( 2296): 	at java.lang.reflect.Method.invokeNative(Native Method)
    W/System.err( 2296): 	at java.lang.reflect.Method.invoke(Method.java:525)
    W/System.err( 2296): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
    W/System.err( 2296): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    W/System.err( 2296): 	at dalvik.system.NativeStart.main(Native Method)
    
    ...

Not very surprising really.

Given that I do not know the private key corresponding to the public key in the Adobe certificate, there was no way the certificate I created for the public key corresponding to the private key I signed the application with could possibly be verified.

The extent of my sleight of hand was simply to ensure that the issuer of the certificate I created was the same as that of the subject of the Adobe certificate.

Arguably it was not really even a sleight of hand.

I do have a second certificate whose subject is the same as that of the Adobe certificate and it does specify the public key corresponding to the private key with which the first certificate was signed.

It just wasn’t the one that got included in the signed signature file.


Copyright (c) 2014 By Simon Lewis. All Rights Reserved.

Unauthorized use and/or duplication of this material without express and written permission from this blog’s author and owner Simon Lewis is strictly prohibited.

Excerpts and links may be used, provided that full and clear credit is given to Simon Lewis and justanapplication.wordpress.com with appropriate and specific direction to the original content.

August 9, 2014

And Another One: Part Four — Certificates And Certificate Chains

1.0 Certificates

The ASN.1 definition of an X.509 Certificate as defined by RFC 2459 looks like this

    Certificate ::= SEQUENCE {
        tbsCertificate      TBSCertificate,
        signatureAlgorithm  AlgorithmIdentifier,
        signature           BIT STRING
    }

An X.509 Certificate is simply a signed TBSCertificate.

The definition of a TBSCertificate looks like this

     TBSCertificate ::= SEQUENCE {
         version                [0] EXPLICIT Version DEFAULT v1(0),
         serialNumber               CertificateSerialNumber,
         signature                  AlgorithmIdentifier,
         issuer                     Name,
         validity                   Validity,
         subject                    Name,
         subjectPublicKeyInfo       SubjectPublicKeyInfo,
         issuerUniqueId         [1] IMPLICIT UniqueIdentifier OPTIONAL,
                                    -- If present, version shall be v2 or v3
         subjectUniqueId        [2] IMPLICIT UniqueIdentifier OPTIONAL,
                                    -- If present, version shall be v2 or v3
         extensions             [3] EXPLICIT Extensions OPTIONAL
                                    -- If present, version shall be v3
     }

1.1 subjectPublicKeyInfo And subject

The

    subjectPublicKeyInfo

field specifies a public key, and the

    subject

field identifies the owner of the specified public key.

1.2 issuer and serialNumber

The

    issuer

field identifies the signer of the TBSCertificate.

This together with the

    serialNumber

field should uniquely identify the certificate.

1.3 Validity

The validity field specifies the period during which the certificate is valid.

The ASN.1 definition of the Validity type looks like this

    Validity ::= SEQUENCE {
        notBefore      Time,
        notAfter       Time }

The public key specified by the certificate should not be used at time T if T is before the value specified by notBefore or after the value specified by notAfter.

Unfortunately, in practice certificates are often issued with such long validity periods that checking the validity really serves no useful purpose.

1.4 Self-Signed Certificates

If the subject and issuer fields are identical then the certificate is self-signed, that is, the signature of the certificate was generated using the private key corresponding to the public key specified by the certificate.

2.0 Certificate Chains

A certificate chain in simply a certificate (A) plus the certificate (B) of the issuer of certificate A, plus the certificate of the issuer of certificate B, and so on.

To put it another way

    certificate[i+1].subject == certificate[i].issuer

A finite certificate chain must necessarily terminate in a self-signed certificate, or terminate arbitrarily and not include all of the certificates back to a self-signed certificate.

The purpose of a certificate chain is to make it possible to verify the signature of the i’th ‘certificate in the chain using the public key specified in the i+1’th certificate.

2.1 Certificate Chains And Trust

Given a certificate chain terminated by a self-signed certificate it is always possible to verify all the certificates in the chain and hence anything signed by subject of the first certificate in the chain.

This is also possible given a chain terminated by a non-self-signed certificate plus the rest of the certificates back to a self-signed certificate obtained from some other source.

In either case what it is possible to do is to establish unequivocally is that something supposedly signed by the subject of the first certificate in the chain was in fact signed by them but that is all.

It is not possible to establish whether the subjects of any of the certificate are who they claim to be.

To do this you must trust one of the certificates in the chain and this cannot be done algorithmically it can only done by policy.

This is usually achieved by having one or more certificates known to the system defined a priori as trust roots.

Any certificate which can be verified directly or indirectly using a trust root can itself be trusted and consequently anything else signed by the subject of a trusted certificate can itself be trusted for some value of trust.

This of course assumes that the subject of a certificate considered to be a trust root is not simply signing every and any certificate that comes their way, and similarly for the subjects of those certificates and so on and so forth.

This is not necessarily a good assumption to make and the longer the certificate chain the less good it becomes but given the way certificates and the public key infrastructure work its all you can do.

3.0 Example

This is a simple example of a certificate chain of length three terminating in a self-signed certificate.


    Certificate[0]
    
    Data:
        Version: 1 (0x0)
        Serial Number:
            8c:f3:8c:e9:05:ed:d1:7c
        Signature Algorithm: sha1WithRSAEncryption
        Issuer:
            C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Android Applications Group, \
                CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
        Validity
            Not Before: Aug  4 10:53:06 2014 GMT
            Not After : Sep  3 10:53:06 2014 GMT
        Subject:
            C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=AndroidApp Flounder Group, \
                CN=AndroidApp Flounder
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public Key: (2048 bit)
                    Modulus (2048 bit):
                        00:8a:84:e0:00:7f:ee:fe:1d:18:57:2d:be:a7:2e:
                        68:aa:6b:6d:26:6d:14:1b:0c:e0:b5:44:46:0c:62:
                        40:7a:d9:d5:46:c3:d0:38:28:29:cb:e4:8f:42:5d:
                        8f:7d:81:78:24:ae:61:f6:a5:9b:a6:b4:0b:b6:f4:
                        01:96:1b:b4:90:b7:74:c7:99:55:33:9d:fc:80:4b:
                        e3:fd:00:4b:99:ee:68:b5:81:6a:60:c3:f2:2e:fc:
                        31:7e:ff:b9:66:24:6f:6b:a0:82:e8:15:f6:cd:d1:
                        b1:b5:05:41:2c:19:e2:f4:92:e9:df:23:94:80:ad:
                        e1:45:41:31:78:52:d2:8d:18:58:c2:0a:a1:ef:9d:
                        5e:d6:5c:60:07:09:6d:87:51:79:42:25:2b:99:0c:
                        35:2d:3d:1f:09:d0:71:05:bb:a7:90:fb:70:e7:26:
                        d9:c6:43:53:35:60:5b:4c:1f:df:38:74:ca:a0:b0:
                        0e:77:9c:fa:7d:c2:32:9a:99:b2:53:6a:c8:fa:ea:
                        0a:3e:b7:99:50:7d:d1:94:3f:a4:2e:18:aa:ff:8a:
                        82:69:0e:2b:83:07:7b:fc:b0:7b:62:7a:99:1e:e7:
                        6b:ab:d6:0d:5e:d2:f2:19:55:af:81:82:e8:d1:db:
                        a9:ea:16:58:32:8a:55:ac:be:8e:cf:87:a0:ed:2d:
                        4f:9f
                    Exponent:
                        65537 (0x10001)
    Signature Algorithm: sha1WithRSAEncryption
        48:7e:34:61:08:14:18:b2:8f:66:3f:2e:58:fd:a5:4c:4f:85:
        fa:d1:36:5b:b9:ba:21:1e:3e:fd:8e:a9:40:23:b6:8a:84:38:
        9f:40:4f:f6:4f:73:a9:f8:79:e7:21:a1:67:32:48:1b:5f:e0:
        5b:6b:13:53:ff:9a:40:41:13:99:e2:0d:eb:6b:15:c5:24:be:
        71:d7:9e:98:af:11:2b:9d:9a:f1:e1:d9:27:27:47:b2:41:3a:
        43:65:ce:b9:c6:7b:00:ee:77:5e:b1:a8:63:e0:f2:fc:94:32:
        42:4f:9b:30:6b:8e:fe:26:e5:0a:ed:1f:ab:9d:5b:48:56:4e:
        30:1d

    Certificate[1]
    
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Certs Group, \
                    CN=Admin/emailAddress=admin@certs.group.ash2.oz
        Validity
            Not Before: Aug  4 10:45:35 2014 GMT
            Not After : Aug  4 10:45:35 2015 GMT
        Subject: C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Android Applications Group, \
                     CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public Key: (1024 bit)
                    Modulus (1024 bit):
                        00:dd:17:06:f9:6a:44:be:96:ed:01:39:e2:fe:5e:
                        99:9e:cf:4f:55:b5:c8:5b:27:42:b6:b5:bf:49:73:
                        41:fd:17:b2:b7:bd:1f:6e:28:07:fc:24:07:57:76:
                        80:5b:88:12:f4:09:28:1d:97:d4:b9:37:7a:2f:52:
                        83:9b:64:60:6f:72:b2:4e:d0:ed:15:d5:26:b2:5a:
                        33:e6:27:37:4f:42:7e:24:36:f1:2e:dc:a8:5d:bd:
                        52:8e:c0:72:62:39:fa:cb:08:f6:4e:e2:89:d0:3b:
                        ab:88:da:e6:a4:18:cc:e3:9d:fb:6d:2e:a1:ac:ec:
                        56:44:f6:8f:d1:c7:b3:e7:c5
                    Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                7B:AB:2E:B9:61:D2:08:3E:78:42:4F:CA:EE:DF:28:3D:27:76:C4:2D
            X509v3 Authority Key Identifier:
                keyid:5B:ED:98:20:92:DD:B5:8F:0F:0F:32:47:29:48:38:BB:F7:52:B0:48
                DirName:/C=OZ/ST=Nowhere/L=Emerald City/O=ASH Two/OU=Certs Group\
                        /CN=Admin/emailAddress=admin@certs.group.ash2.oz
                serial:EF:55:32:3F:F5:CF:64:E5
    
    Signature Algorithm: sha1WithRSAEncryption
        98:a1:e6:be:33:06:94:1f:93:e1:c5:1a:a4:53:5c:c5:ad:f0:
        b7:c4:bd:f3:dd:22:2e:f1:aa:0e:c7:08:42:1b:9a:f8:1c:f4:
        05:c2:a2:96:a3:ea:d6:5d:7d:ee:65:78:4c:24:5d:35:8b:0b:
        7c:fe:b3:a4:c7:5f:b6:45:f0:3b:f2:5d:8c:32:fa:8e:2d:0b:
        6e:10:1c:5c:3c:55:d4:f0:f3:c3:61:53:22:6a:65:93:d0:2a:
        a4:29:09:61:8e:46:9c:ab:47:0b:74:16:97:d3:30:51:4f:eb:
        ad:e1:4f:6e:83:a9:f6:11:0f:7d:ab:97:73:f9:8a:cf:43:53:
        f8:6d

    Certificate[2]
    
    Data:
        Version: 3 (0x2)
        Serial Number:
            9a:32:99:e8:05:ee:62:db
            Signature Algorithm: sha1WithRSAEncryption
            Issuer:
                C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Android Applications Group, \
                    CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
            Validity
                Not Before: Aug  5 16:57:20 2014 GMT
                Not After : Aug  5 16:57:20 2015 GMT
            Subject:
                C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Android Applications Group, \
                    CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    RSA Public Key: (1024 bit)
                        Modulus (1024 bit):
                            00:c6:27:36:f5:fd:33:26:14:7b:a9:1b:10:84:fc:
                            7b:58:e3:cf:21:b9:28:50:4b:b9:d0:9b:73:5b:e4:
                            81:06:be:0d:b6:ff:d2:d4:06:bd:bd:63:3d:e6:65:
                            f3:10:e5:39:5b:4c:e1:96:e4:fe:a3:e3:52:c1:6b:
                            bd:a0:e8:fb:a8:11:f8:0c:68:ee:6b:1b:e0:c8:9d:
                            41:0a:41:c6:dd:ff:1b:4c:c4:a1:9b:17:85:58:4a:
                            3d:4e:88:4f:2e:ea:d3:28:8e:23:a1:d9:92:ba:87:
                            b6:91:d9:07:8b:c2:9a:e3:75:18:36:3e:fc:12:ae:
                            ff:3a:4b:3a:e7:21:a1:08:2d
                        Exponent: 65537 (0x10001)
            X509v3 extensions:
                X509v3 Subject Key Identifier:
                    79:59:43:52:D9:04:7D:C0:EA:A8:14:37:BB:7B:85:92:91:44:07:D1
                X509v3 Authority Key Identifier:
                    keyid:79:59:43:52:D9:04:7D:C0:EA:A8:14:37:BB:7B:85:92:91:44:07:D1
                    DirName:/C=OZ/ST=Nowhere/L=Emerald City/O=ASH Two/OU=Android Applications Group \
                            /CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
                    serial:9A:32:99:E8:05:EE:62:DB
    
                X509v3 Basic Constraints:
                    CA:TRUE
    Signature Algorithm: sha1WithRSAEncryption
        a2:7b:0f:7d:02:ee:5a:b4:e0:b7:78:33:5d:59:9b:13:be:71:
        98:6b:2e:44:95:56:e5:69:78:49:99:5d:f9:14:a8:4f:1c:fc:
        4d:13:f7:2a:cd:eb:cc:97:7c:41:1e:24:2b:d4:56:3d:0a:90:
        cd:7b:9f:af:84:99:9a:bc:c7:63:3a:24:46:7c:f7:06:48:f9:
        7c:10:9b:58:ee:2e:07:1b:a9:66:66:d0:cc:e7:cb:f2:8c:53:
        6b:a8:d3:2e:a6:d2:f0:f4:ca:65:fb:66:73:18:86:8a:30:ef:
        f7:09:27:56:00:5f:e2:30:d8:5e:a2:6b:d6:22:af:bd:18:59:
        b9:7b

Copyright (c) 2014 By Simon Lewis. All Rights Reserved.

Unauthorized use and/or duplication of this material without express and written permission from this blog’s author and owner Simon Lewis is strictly prohibited.

Excerpts and links may be used, provided that full and clear credit is given to Simon Lewis and justanapplication.wordpress.com with appropriate and specific direction to the original content.

Blog at WordPress.com.

%d bloggers like this: