=========================[ Readings ]========================= Android apps must carry a cryptographic signature by their developer or vendor. Unsigned apps will not be installed by newer Android systems. Signing involves creating an RSA key pair (public and private key), a one-way hash function to "digest" the app's classes and resources (in version 1 signing scheme) or the whole APK file (in v2 signing scheme). The process of signing consists of applying the hash function, and then encrypting its output, the digest byte string, with the private key. Whoever wants to verify that the file is exactly as you had it when you signed it only needs to (1) decrypt the digest with your public key (this key is in your certificate packaged with the app, together with your name and some other info, such as which one-way function was used), and (2) apply the same one-way function to get the digest of the file. If the decrypted digest from (1) matches the actual digest from (2), the file is what you signed, proving that (a) it was not tampered with and (b) whoever signed it was in possession of your private key. It's a very graceful scheme, one of the chief achievements of theoretical computer science. To see what a one-way hash function does, choose some file, do "sha1sum " then change the file minimally, and try again. For example, you can change just one bit, by changing "A" to "B"; the change in the sha1 digest will be drastic and unpredictable. The idea of a one-way function is that it should be really hard to produce another file that hashes to the same value. This means that you can judge if a file has been changed by computing a digest and comparing it with a saved digest. Only you (or someone in possession of your private key) can create a signature that, when decrypted with your public key, matches the hash digest of the file. If the file is changed, its digest also changes; for the decrypted signature to match this new digest, the attacker would need your private key. A non-mathematical summary of asymmetric cryptography (such as RSA and the newer "elliptic curves" algorithms) can be found here: Short summary: http://searchsecurity.techtarget.com/definition/asymmetric-cryptography With pretty pictures: http://etutorials.org/Programming/Programming+.net+security/Part+III+.NET+Cryptography/Chapter+15.+Asymmetric+Encryption/15.1+Asymmetric+Encryption+Explained/ (ignore references to .NET; other frameworks use the same algorithms the same way). Finer points on how asymmetric cryptography is related to signing: https://www.cs.cornell.edu/courses/cs5430/2015sp/notes/rsa_sign_vs_dec.php (this link unfortunately contains a typo in its encryption part of OEAP: it should be G(r), not H(r) for X in OAEP-pre(m). See https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding) ==============[ Certificates and signing authorities ]============== How can users access your public key and be sure it's yours, so that they can use it to check if an app or document has indeed been signed by you? This is done by somebody they can trust verifying your identity in some real-world way, then taking your public key and some strings that include your name and organization, and signing them as a unit. This unit is called a _certificate_, and includes the signature created by this trustworthy someone. It is packaged with your app. Then the users can obtain the signer's public key, and validate that the certificate that contains _your_ public key has indeed been signed by the trusted signer (who hopefully performed due diligence). But who is this trusted signer and how to get their public key? There are two basic approaches to this problem: the decentralized one, called the Web of Trust and the centralized one, called the Public Key Infrastructure (PKI). The Debian Linux project uses a web of trust: an existing developer must vouch for you and sign your certificate (cert, for short). Then the users can follow the path of trust from that signer to the project's main keys. Their process is described here: https://wiki.debian.org/Keysigning Your browser uses the PKI approach: certificates of organizations that make it their business to validate and sign certs are packaged with your browser. These organizations are called Certifying Authorities, or CAs. There are many of them, and any one's public key (contained in any one of their certs) is assumed to be good. You can see these CA certs in Firefox by going to Preferences and searching for certificates, then going to the CAs tab. This model has an obvious weakness: should any one of these CAs get compromised, i.e., their private key falls into the hands of attackers, your browser will trust the new fake certs they'd sign with it. No matter that, say, Amazon's website certificate was signed by Amazon's own CA and now it's signed by some Dutch CA you don't know about; your browser would still accept it. To prevent it, companies implement "certificate pinning": they restrict the list of CAs whose signatures they trust. Compromises of CAs are big news. E.g., https://nakedsecurity.sophos.com/2011/03/24/fraudulent-certificates-issued-by-comodo-is-it-time-to-rethink-who-we-trust/ or https://threatpost.com/final-report-diginotar-hack-shows-total-compromise-ca-servers-103112/77170/ (DigiNotar was trusted by the Dutch government to handle its certs) or http://www.computerweekly.com/news/450429177/Researchers-uncover-strong-trade-in-code-signing-certificates Of course, you can run your own CA; free software like OpenSSL gives you all the functionality in generating key pairs and creating and signing certificates (e.g., https://gist.github.com/Soarez/9688998 or https://jamielinux.com/docs/openssl-certificate-authority/) Google's model allows developers to generate their own certificates, but has a PKI for Google's trusted apps. That way you can choose who you trust, but Google's apps are in their own higher-trust world. Google uses a different model for signing the Android OS images and updates; we'll talk about these next week. Android Studio comes packaged with a list of CAs similar to that of your browser. These are located in a database called a "Java keystore" and can be examined with Java's keytool: keytool -list -v -keystore '/Applications/Android Studio 3.0 Preview.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts'| less ("file '/Applications/Android Studio 3.0 Preview.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts'" gives: /Applications/Android Studio 3.0 Preview.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts: Java KeyStore ) See https://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html about keytool. ===================[ Signing apps on Android ]====================== Apps are prevented from accessing each other's files and other resources, unless they share the same UID number (Linux User ID). The Android OS will only allow it to happen if the apps are signed by the same key. The same goes for app updates: an update is only allowed to proceed if it is signed by the same key as the original app. This assures that only you can change your app (so long as you still have your private key and no one else does). Read about APK signing: https://source.android.com/security/apksigning/ ======================[ What gets signed and how ]====================== There are two signing schemes: the original v1 and the recent v2. V1 applied to individual files in the APK, _after_ the APK has been unzipped. An APK v1 is just a ZIP archive with some specially named directories and files, like the META-INF/ directory and the MANIFEST.MF and CERT.RSA in it. This means that attackers could manipulate the ZIP file format; being a complex format, it lends itself to various attacks, like the Android Master Key attack. V2 corrected this, by signing the entire ZIP archive, and thus making tampering with its data evident during validation of the signature. Here is the structure of a ZIP archive at a glance: https://raw.githubusercontent.com/corkami/pics/master/binary/zip101/zip101.pdf Here's where the v2 APK signature block goes: https://source.android.com/security/apksigning/v2#verification Here is more information on the Android Master Key exploits, a masterpiece of its kind: http://www.saurik.com/id/17 http://www.saurik.com/id/18 http://www.saurik.com/id/19 Another fun manipulation of v1 signatures: https://www.blackhat.com/docs/eu-14/materials/eu-14-Apvrille-Hide-Android-Applications-In-Images-wp.pdf You can look at the certificate of an APK file by unzipping it (create a new directory) and then using Java's keytool to examine the cert. E.g., for my Compass app: mkdir compass cp AndroidStudioProjects/Compass/app/build/outputs/apk/debug/app-debug.apk compass/ cd compass unzip app-debug.apk cd META-INF/ keytool -v -printcert -file CERT.RSA You will see that this cert is the debug cert, automatically created by your Android Studio when you installed it. Its private key lives (on MacOS) in ~/.android/debug.keystore. This keystore can be examined with keytool -list -v -keystore ~/.android/debug.keystore =========================[ Binder ]========================= Binder is a mechanism of Linux Inter-process communication that apps use to interact with other apps and Android services. Linux on servers and desktops uses other forms of IPC (Unix sockets, pipes, shared memory, semaphores & message queues, etc.; see http://www.tldp.org/LDP/tlk/ipc/ipc.html). However, on Android Binder is the single core IPC mechanism is use by apps and services, whereas on other Linux platforms it did not see much use. When your app sends an Intent, it travels all the way down the Android stack: from your Java class to the Java Virtual Machine (Dalvik or ART, for newer Android versions), from the internals of the VM to the native library code, from the library to the kernel, where Binder resides, and then back up the stack to another Android process. Thus Binder mediates all communications between the apps, and is a key part of both security and scheduling (because Binder is how apps and services "listen" for intents: they register with Binder to do so, and get woken up by Binder when a matching message arrives). More details here: http://newandroidbook.com/files/Andevcon-Binder.pdf (IPC discussion starts with slide 5)