Sunday, February 22, 2015

Best practices to protect data in Android applications Using Cryptography - Part 2


Cryptography is the practice and study of techniques for secure communication, various aspects in information security such as data confidentialitydata integrityauthentication. Cryptography is heavily based on mathematical theory and computer science practice; cryptographic algorithms are designed
around computational hardness assumptions, making such algorithms hard to break in practice by any adversary. 

In a much simple language Cryptography is a method of storing and transmitting data in a particular form so that those for whom it is intended can read and process it. The term is most often associated with scrambling plaintext (ordinary text, sometimes referred to as cleartext) into cipherText ( a process called encryption), then back again (known as decryption)

On a high level Cryptography is divided in to two basic forms in Android
  • Symmetric-key cryptography
  • Assymetric-key/Public-key cryptography

 Android Cryptography API provides three main packages, to start with will share a sample code.
  • javax.crypto: This package provides the classes and interfaces for cryptographic applications implementing algorithms for encryption, decryption, or key agreement.
  • javax.crypto.interfaces: This package provides the interfaces needed to implement the key agreement algorithm.
  • javax.crypto.spec: This package provides the classes and interfaces needed to specify keys and parameter for encryption.


Symmetric-key cryptographSymmetric-key cryptography refers to encryption methods in which both the sender and receiver share the same key. 

Public-key cryptography, where single key is used for encryption and decryption
Advanced Encryption Standard (AES) :  The algorithm described by AES is a form of symmetric-key algorithm.

Description of the cipher : AES is based on a design principle known as a substitution-permutation network, combination of both substitution and permutation, and is fast in both software and hardware.

High-level description of the algorithm, just to provide an overview of how this algorithm works.

  1. KeyExpansions—round keys are derived from the cipher key using Rijndael's key schedule. AES requires a separate 128-bit round key block for each round plus one more.
  2. InitialRound
    1. AddRoundKey—each byte of the state is combined with a block of the round key using bitwise xor.
  3. Rounds
    1. SubBytes—a non-linear substitution step where each byte is replaced with another according to a lookup table.
    2. ShiftRows—a transposition step where the last three rows of the state are shifted cyclically a certain number of steps.
    3. MixColumns—a mixing operation which operates on the columns of the state, combining the four bytes in each column.
    4. AddRoundKey
  4. Final Round (no MixColumns)
    1. SubBytes
    2. ShiftRows
    3. AddRoundKey.

Android Example to encrypt and decrypt using AES Algorithms


package com.example.samplework;
import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.SecretKeySpec; import android.app.Activity; import android.os.Bundle; import android.util.Base64; import android.util.Log; import android.widget.TextView;
public class SymmetricCryptoAES extends Activity {
static final String TAG = "SymmetricAlgorithmAES";
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.crypto);
// Text to be encoded
String actualText = "Testing Symmetric cryptography using AES algorithm";
TextView actText = (TextView) findViewById(R.id.original); actText.setText("\n[ACTUAL TEXT]:\n" + actualText + "\n");
// Set up secret key spec for 128-bit AES encryption and decryption
SecretKeySpec sks = null; try { SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed("any data used as random seed".getBytes());
KeyGenerator kg = KeyGenerator.getInstance("AES"); kg.init(128, sr); sks = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES"); } catch (Exception e) {
Log.e(TAG, "AES secret key spec error");
}
// Encode the original data with AES
byte[] encodedBytes = null; try { Cipher c = Cipher.getInstance("AES"); c.init(Cipher.ENCRYPT_MODE, sks); encodedBytes = c.doFinal(actualText.getBytes()); } catch (Exception e) {
Log.e(TAG, "AES encryption error");
} TextView encodedText = (TextView) findViewById(R.id.encoded);
encodedText.setText("[ENCODED TEXT USING AES ALGORITHM]:\n"
+ Base64.encodeToString(encodedBytes, Base64.DEFAULT) + "\n");
// Decode the encoded data with AES
byte[] decodedBytes = null; try { Cipher c = Cipher.getInstance("AES"); c.init(Cipher.DECRYPT_MODE, sks); decodedBytes = c.doFinal(encodedBytes); } catch (Exception e) {
Log.e(TAG, "AES decryption error");
} TextView decodedText = (TextView) findViewById(R.id.decoded);
decodedText.setText("[DECODED TEXT USING AES ALGORITHM]:\n"
+ new String(decodedBytes) + "\n"); } }

Output of above code on device which shows the encoded and decode text using AES algorithm.


Assymetric-key/Public-key cryptography : public-key (also, more generally, called asymmetric key) cryptography in which two different but mathematically related keys are used—a public key and a private key. A public key system is so constructed that calculation of one key (the 'private key') is computationally infeasible from the other (the 'public key'), even though they are necessarily related. Instead, both keys are generated secretly, as an interrelated pair.

Public-key cryptography, where different keys are used for encryption and decryption
RSA is one of the first practicable public-key cryptosystems and is widely used for secure data transmission. RSA stands for Ron RivestAdi Shamir and Leonard Adleman, who first publicly described the algorithm in 1977. In such acryptosystem, the encryption key is public and differs from the decryption key which is kept secret. In RSA, this asymmetry is based on the practical difficulty of factoring the product of two large prime numbers, the factoring problem

High-Level description of the algorithm : The RSA algorithm involves three steps: 
  • key generation : RSA involves a public key and a private key. The public key can be known by everyone and is used for encrypting messages. Messages encrypted with the public key can only be decrypted in a reasonable amount of time using the private key. The keys for the RSA algorithm are generated the following way:
    • Choose two distinct prime numbers p and q.
    • Compute n = pq.
    • Compute Ï†(n) = φ(p)φ(q) = (p − 1)(q − 1) = n - (p + q -1), where φ is Euler's totient function.
    • Choose an integer e such that 1 < e < φ(n) and gcd(e, φ(n)) = 1; i.e., e and φ(n) are coprime.
      • e is released as the public key exponent.
    • Determine d as d ≡ e−1 (mod φ(n)); i.e., d is the multiplicative inverse of e (modulo φ(n)).

      • d is kept as the private key exponent.


  • Encryption : Alice transmits her public key (ne) to Bob and keeps the private key d secret. Bob then wishes to send message M to Alice.
    He first turns M into an integer m, such that 0 ≤ m < n by using an agreed-upon reversible protocol known as a padding scheme. He then computes the ciphertext ccorresponding to
     c \equiv m^e \pmod{n}
    This can be done efficiently, even for 500-bit numbers, using Modular exponentiation. Bob then transmits c to Alice.
    Note that at least nine values of m will yield a ciphertext c equal to m,
  • Decryption : Alice can recover m from c by using her private key exponent d via computing
     m \equiv c^d \pmod{n}
    Given m, she can recover the original message M by reversing the padding scheme.


RSA algorithm example :
  • Choose p = 3 and q = 11
  • Compute n = p * q = 3 * 11 = 33
  • Compute φ(n) = (p - 1) * (q - 1) = 2 * 10 = 20
  • Choose e such that 1 < e < φ(n) and e and n are coprime. Let e = 7
  • Compute a value for d such that (d * e) % φ(n) = 1. One solution is d = 3 [(3 * 7) % 20 = 1]
  • Public key is (e, n) => (7, 33)
  • Private key is (d, n) => (3, 33)
  • The encryption of m = 2 is c = 27 % 33 = 29
  • The decryption of c = 29 is m = 293 % 33 = 2

Android Example to encrypt and decrypt using RSA Algorithms


package com.example.samplework;

import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import javax.crypto.Cipher; import android.app.Activity; import android.os.Bundle; import android.util.Base64; import android.util.Log; import android.widget.TextView;
public class AsymmetricCryptoRSA extends Activity {
static final String TAG = "AsymmetricAlgorithmRSA";
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.crypto);
// Text to be encoded
String actualText = "Testing Asymmetric cryptography using RSA algorithm";
TextView actText = (TextView) findViewById(R.id.original); actText.setText("\n[ACTUAL TEXT]:\n" + actualText + "\n");
// Generate key pair for 1024-bit RSA encryption and decryption
PublicKey publicKey = null; PrivateKey privateKey = null; try { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(1024); KeyPair kp = kpg.genKeyPair(); publicKey = kp.getPublic();// kp.getPublic(); privateKey = kp.getPrivate(); } catch (Exception e) {
Log.e(TAG, "RSA key pair error");
}
// Encode the original data with RSA private key
byte[] encodedBytes = null; try { Cipher c = Cipher.getInstance("RSA"); c.init(Cipher.ENCRYPT_MODE, privateKey); encodedBytes = c.doFinal(actualText.getBytes()); } catch (Exception e) {
Log.e(TAG, "RSA encryption error");
} TextView encodedText = (TextView) findViewById(R.id.encoded);
encodedText.setText("[ENCODED TEXT USING RSA ALGORITHM]:\n"
+ Base64.encodeToString(encodedBytes, Base64.DEFAULT) + "\n");
// Decode the encoded data with RSA public key
byte[] decodedBytes = null; try { Cipher c = Cipher.getInstance("RSA"); c.init(Cipher.DECRYPT_MODE, (java.security.Key) publicKey); decodedBytes = c.doFinal(encodedBytes); } catch (Exception e) {
Log.e(TAG, "RSA decryption error");
} TextView decodedText = (TextView) findViewById(R.id.decoded);
decodedText.setText("[DECODED TEXT USING RSA ALGORITHM]:\n"
+ new String(decodedBytes) + "\n"); } }
Output of above code on device which shows the encoded and decode text using RSA algorithm.



Saturday, February 21, 2015

Best practices to protect data in Android applications - Part 1


Android has security features built into the operating system that significantly reduce the frequency and impact of application security issues. The system is designed so you can typically build your apps with
default system and file permissions and avoid difficult decisions about security.

It is important to be familiar with Android security best practices, following these practices as general coding habits will reduce the likelihood of inadvertently introducing security issues that adversely affect your users.:


  • The Android Application runs in a Sandbox, which automatically isolates your app data and code execution from other apps.

  • User-granted permissions is another level of security provided to restrict access to system features and user data.

  • Application-defined permissions to control application data on a per-app basis.

  • Storing Data
    • Using Internal Storage : By default, files that you create on internal storage are accessible only to your app. You should generally avoid using the MODE_WORLD_WRITEABLE or MODE_WORLD_READABLE modes for IPC files because they do not provide the ability to limit data access to particular applications, nor do they provide any control on data format.
    • Using External Storage : It is strongly recommend that you not store executables or class files on external storage prior to dynamic loading. If your app does retrieve executable files from external storage, the files should be signed and cryptographically verified prior to dynamic loading.
    • Using Content Providers : Content providers offer a structured storage mechanism that can be limited to your own application or exported to allow access by other applications. If you do not intend to provide other applications with access to yourContentProvider, mark them as android:exported=false in the application manifest. Otherwise, set theandroid:exported attribute "true" to allow other apps to access the stored data.

  • Using Permissions - As Android sandboxes applications from each other, applications must explicitly share resources and data. They do this by declaring the permissions they need for additional capabilities not provided by the basic sandbox, including access to device features such as the camera.
    • Requesting permissions : In general, it is recommend using access controls other than user confirmed permissions where possible because permissions can be confusing for users. For example, consider using the signature protection level on permissions for IPC communication between applications provided by a single developer.
    • Creating permissions : Generally, you should strive to define as few permissions as possible while satisfying your security requirements. If you must create a new permission, consider whether you can accomplish your task with a "signature" protection level. Signature permissions are transparent to the user and only allow access by applications signed by the same developer as application performing the permission check. If you create a permission with the "dangerous" protection level, there are a number of complexities that you need to consider:
      • The permission must have a string that concisely expresses to a user the security decision they will be required to make.
      • The permission string must be localized to many different languages.
      • Users may choose not to install an application because a permission is confusing or perceived as risky.
      • Applications may request the permission when the creator of the permission has not been installed.

  • Using NetworkingNetwork transactions are inherently risky for security, because it involves transmitting data that is potentially private to the user.
    • Using IP Networking : Networking on Android is not significantly different from other Linux environments. The key consideration is making sure that appropriate protocols are used for sensitive data, such as HttpsURLConnection for secure web traffic. We prefer use of HTTPS over HTTP anywhere that HTTPS is supported on the server, because mobile devices frequently connect on networks that are not secured, such as public Wi-Fi hotspots. Authenticated, encrypted socket-level communication can be easily implemented using the SSLSocket class. 

  • Using WebViewBecause WebView consumes web content that can include HTML and JavaScript, improper use can introduce common web security issues such as cross-site-scripting (JavaScript injection). Android includes a number of mechanisms to reduce the scope of these potential issues by limiting the capability of WebView to the minimum functionality required by your application. 
    • If your application does not directly use JavaScript within a WebView, do not call setJavaScriptEnabled()
    • Use addJavaScriptInterface() with particular care because it allows JavaScript to invoke operations that are normally reserved for Android applications. If you use it, expose addJavaScriptInterface() only to web pages from which all input is trustworthy. If untrusted input is allowed, untrusted JavaScript may be able to invoke Android methods within your app. In general, we recommend exposing addJavaScriptInterface()only to JavaScript that is contained within your application APK.
    • f your application accesses sensitive data with a WebView, you may want to use the clearCache() method to delete any files stored locally. Server-side headers like no-cache can also be used to indicate that an application should not cache particular content.
    • Devices running platforms older than Android 4.4 (API level 19) use a version of webkit that has a number of security issues. As a workaround, if your app is running on these devices, it should confirm that WebView objects display only trusted content. You should also use the updatable security Provider object to make sure your app isn’t exposed to potential vulnerabilities in SSL, as described in Updating Your Security Provider to Protect Against SSL Exploits. If your application must render content from the open web, consider providing your own renderer so you can keep it up to date with the latest security patches.

  • Handling CredentialsIn general, it is recommend to minimize the frequency of asking for user credentials—to make phishing attacks more conspicuous, and less likely to be successful. Instead use an authorization token and refresh it.
    • Where possible, username and password should not be stored on the device. Instead, perform initial authentication using the username and password supplied by the user, and then use a short-lived, service-specific authorization token.
    • Services that will be accessible to multiple applications should be accessed using AccountManager. If possible, use the AccountManager class to invoke a cloud-based service and do not store passwords on the device.
    • After using AccountManager to retrieve an AccountCREATOR before passing in any credentials, so that you do not inadvertently pass credentials to the wrong application.
    • If credentials are to be used only by applications that you create, then you can verify the application which accesses the AccountManager using checkSignature(). Alternatively, if only one application will use the credential, you might use a KeyStore for storage.

  • Using CryptographyIn addition to providing data isolation, supporting full-filesystem encryption, and providing secure communications channels, Android provides a wide array of algorithms for protecting data using cryptography. 
Will explain with an example on using Cryptography in Part 2

Saturday, February 7, 2015

Code Obfuscation and Optimization using Proguard tool



I have been thinking of writing on Code optimization and obfuscation from quiet a long time as I got chance to dive into obfuscation in my recent project, the basic mistakes we make while coding and how small things help us optimize. Also will cover the bullet points to keep in mind while coding.

Code optimization is a set of methods of code modification to improve code quality and efficiency.
A program may be optimized so that it becomes of a smaller size, consumes less memory, executes more rapidly, or performs fewer input/output operations.

Obfuscation is the deliberate act of creating obfuscated code, i.e. source or machine code that is difficult for humans to understand. Programmers may deliberately obfuscate code to conceal its purpose (security through obscurity) or its logic, in order to prevent tampering, deter reverse engineering, or as a puzzle or recreational challenge for someone reading the source code.

Proguard most popular open source code optimization and obfuscation tool provided as part of the Android SDK, can be a double edge sword -- it presents bootstrapping challenges but when applied correctly, provides tremendous benefits!


The ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names. The result is a smaller sized .apk file that is more difficult to reverse engineer. Because ProGuard makes your application harder to reverse engineer, it is important that you use it when your application utilizes features that are sensitive to security like when you are Licensing Your Applications.


ProGuard is integrated into the Android build system, so you do not have to invoke it manually. ProGuard runs only when you build your application in release mode, so you do not have to deal with obfuscated code when you build your application in debug mode. Having ProGuard run is completely optional, but highly recommended.

This document describes how to enable and configure ProGuard as well as use the retrace tool to decode obfuscated stack traces.

Steps to use proguard tool properly



  1. Create android library project
  2. In Terminal go to sdk/tools and run below command to generate build.xml at the root folder of library project. build.xml basically has all the steps to build the .apk file and has property to use local project.properties file 
    <loadproperties srcFile="project.properties" />
    .
    /android update project -p /root path of your android library project
  3. To enable proguard, please check the predefined proguard.config refered in project.properties and uncomment it proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt

    1. In proguard-project.txt add below lines


    This would actually take the original jar generated in bin->proguard folder as an input to generate obfuscated jar generated at the path provided under -outjars

    The methods that needs to be accessed from another project or the code that we don't want to obfuscate can be kept without obfuscation using, similar thing can be done with class members also.

    -keepclassmembernames class *
    -injars       Path-to-android-project/bin/proguard/original.jar
    -outjars      Path-to-android-project/bin/samplelibraryout.jar
    -libraryjars  <java.home>/lib/rt.jar
    -printmapping out.map
    
    -keepparameternames
    -renamesourcefileattribute SourceFile
    -keepattributes Exceptions,InnerClasses,Signature,Deprecated,
                    SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
    
    -keep public class * {
        public protected *;
    }
    
    -keepclassmembernames class * {
        java.lang.Class class$(java.lang.String);
        java.lang.Class class$(java.lang.String, boolean);
    }
    
    -keepclasseswithmembernames class * {
        native <methods>;
    }
    
    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    -keepclassmembers class * implements java.io.Serializable {
        static final long serialVersionUID;
        private static final java.io.ObjectStreamField[] serialPersistentFields;
        private void writeObject(java.io.ObjectOutputStream);
        private void readObject(java.io.ObjectInputStream);
        java.lang.Object writeReplace();
        java.lang.Object readResolve();
    }

    5. Similarly, to optimize add line in project.properties
    proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt

    6. Now in Terminal go to library project path and run below command, obfuscation or optimization can only be applied to a release build, hence the below commands.
    ant clean
    ant release


    Thats it an obfuscated and optimized jar is generated. 



    Obfuscated jar can be tested using any of the decompilers available, the one I use is JD-Decompiler.


    The basic requirement optimization methods should comply with is that an optimized program must have the same output and side effects as its non-optimized version. This requirement, however, may be ignored in case the benefit from optimization is estimated to be more important than probable consequences of a change in the program behavior.

    Also, few other things that should be kept in mind while optimizing the code.
    • Only optimize code if you need to
    • Only optimize where it counts
    • Use the profiler to see where to optimize
    • The profiler won't help you on the device, so use the System timer on the hardware
    • Always study your code and try to improve the algorithms before using low-level techniques
    • Drawing is slow, so use the Graphics calls as sparingly as possible
    • Use setClip() where possible to minimize the drawing area
    • Keep as much stuff as possible out of loops
    • Pre-calculate and cache like crazy
    • Strings create garbage and garbage is bad so use StringBuffers instead
    • Assume nothing
    • Use static final methods where possible and avoid the synchronized modifier
    • Pass as few parameters as possible into frequently-called methods
    • Where possible, remove method calls altogether
    • Unroll loops
    • Use bit shift operators instead of division or multiplication by a power of two
    • You can use bit operators to implement circular loops instead of modulo
    • Try to compare to zero instead of any other number
    • Array access is slower, so cache array elements
    • Eliminate common sub-expressions
    • Local variables are faster than instance variables
    • Don't wait() if you can callSerially()
    • Use small, close constants in switch() statements
    • Look inside your Fixed Point math library and optimize it
    • Unravel nested FP calls to reduce casting
    • Division is slower than multiplication, so multiply by the inverse instead of dividing
    • Use tried and tested algorithms
    • Use proprietary high-performance APIs with care to preserve portability