Cryptography is the practice and study of techniques for secure communication, various aspects in information security such as data confidentiality, data integrity, authentication. 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 cryptograph : Symmetric-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.
- 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.
- InitialRound
- AddRoundKey—each byte of the state is combined with a block of the round key using bitwise xor.
- Rounds
- SubBytes—a non-linear substitution step where each byte is replaced with another according to a lookup table.
- ShiftRows—a transposition step where the last three rows of the state are shifted cyclically a certain number of steps.
- MixColumns—a mixing operation which operates on the columns of the state, combining the four bytes in each column.
- AddRoundKey
- Final Round (no MixColumns)
- SubBytes
- ShiftRows
- 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";@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.crypto);// Text to be encodedString 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 decryptionSecretKeySpec 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 AESbyte[] 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 AESbyte[] 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 Rivest, Adi 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 (n, e) 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 toThis 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
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";@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.crypto);// Text to be encodedString 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 decryptionPublicKey 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 keybyte[] 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 keybyte[] 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.