We write simple methods to use the Data Encryption Standard (DES) to encrypt and decrypt a string using an 8-byte password. Our encryption library is named PacktPlatformLibrary
.
Since this code is external to the framework and does not need to be tightly integrated with the system, we will place it in a separate directory called /vendor
under ANDROID_SRC
. Usually, inside this directory, vendor-specific files are added. Create ANDROID_SRC/vendor/PacktVendor
. Inside that, include the following one-liner Android.mk
file, so that subsequent make files are called during build.
We start out by writing a one-liner make file for the project. This file is saved as
Android.mk
and is the top-level make file:include $(call all-subdir-makefiles)
Under PacktVendor, create a directory named PacktPlatformLibrary. Inside this we will create the platform library and write its code.
Create a directory named
java/packt/platformlibrary
underPacktPlatformLibrary/
. This will hold the source code for the library.Save the following code as
PacktPlatformLibrary.java
:package packt.platformlibrary; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import android.util.Log; public class PacktPlatformLibrary { private static final String TAG = "packt.PlatformLibrary"; /* key has to be 8 bytes */ public static byte [] encryptDES(String key, String data) { byte [] encr = null; DESKeySpec keySpec; try { keySpec = new DESKeySpec(key.getBytes("UTF8")); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey skey = keyFactory.generateSecret(keySpec); Cipher cipher = Cipher.getInstance("DES"); cipher.init(Cipher.ENCRYPT_MODE, skey); encr = cipher.doFinal(data.getBytes("UTF8")); } catch (InvalidKeyException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (UnsupportedEncodingException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchAlgorithmException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (InvalidKeySpecException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchPaddingException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (IllegalBlockSizeException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (BadPaddingException e) { Log.e(TAG, Log.getStackTraceString(e)); } return encr; }
The preceding method simply DES encrypts a string. You can replace the function with anything you like. The point of the example is to demonstrate a platform library:
public static String decryptDES(String key, byte [] data) { DESKeySpec keySpec; byte [] unencr = null; try { keySpec = new DESKeySpec(key.getBytes("UTF8")); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey skey = keyFactory.generateSecret(keySpec); Cipher cipher = Cipher.getInstance("DES");// cipher is not thread safe cipher.init(Cipher.DECRYPT_MODE, skey); unencr = cipher.doFinal(data); } catch (InvalidKeyException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (UnsupportedEncodingException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchAlgorithmException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (InvalidKeySpecException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchPaddingException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (IllegalBlockSizeException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (BadPaddingException e) { Log.e(TAG, Log.getStackTraceString(e)); } return new String(unencr); } public static void printHex(byte [] data) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < data.length; i++) { sb.append(Integer.toString((data[i] & 0xff) + 0x100, 16).substring(1)); } Log.i("PacktDESTest", "DES bytes: " + sb.toString()); } }
Similarly,
decryptDES
performs the opposite function ofencryptDES
. You can again choose to replace this with a function of your choice. If you choose to do so, keep in mind that later files will have to be adjusted a bit based on the new functions. However, no change is needed in any of the build files:The Android system requires that an XML file is to be created for every new platform library. Create an XML file at
ANDROID_SRC/vendor/PacktVendor/PacktPlatformLibrary/
. Save this XML file asPacktPlatformLibrary.xml
:<permissions> <library name="PacktPlatformLibrary" file="/system/framework/PacktPlatformLibrary.jar"/> </permissions>
Finally, we need a make file to pull all the components together. Create an
Android.mk
file in the same directory as the preceding file:This code is saved as Android.mk # # PacktPlatformLibrary LOCAL_PATH := $(call my-dir) # the library # ============================================================ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_MODULE_TAGS := optional # This is the target being built. LOCAL_MODULE:= PacktPlatformLibrary include $(BUILD_JAVA_LIBRARY) # the documentation # ============================================================ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) $(call all-subdir-html-files) LOCAL_MODULE:= PacktPlatformLibrary LOCAL_DROIDDOC_OPTIONS := PacktPlatformLibrary LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_DROIDDOC_USE_STANDARD_DOCLET := true include $(BUILD_DROIDDOC) ######################## include $(CLEAR_VARS) LOCAL_MODULE := PacktPlatformLibrary.xml LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := ETC # This will install the file in /system/etc/permissions # LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions LOCAL_SRC_FILES := $(LOCAL_MODULE) include $(BUILD_PREBUILT)
The preceding file has three sections. The first compiles the java code for the library and creates a JAR file. The name of this JAR is specified in the
LOCAL_MODULE
tag. Next, if the project directory contains documentation, that is built. Finally, we need to ensure the XML file is added to/system/etc/permissions/
in the system image.LOCAL_MODULE_CLASS
is used to specify this. Now, we need to build the components. On a terminal, insideANDROID_SRC
, issue the following command:make PacktPlatformLibrary
The following command will compile the java code, generate a signed JAR, and place it in
system/framework/
:make PacktPlatformLibrary.xml
This will place the XML file at
/system/etc/permissions/
.
The platform library has two main components. One is the library itself, which is written in Java or C, and is packaged into a JAR (with an optional shared object if native code is used). The second component is an XML file that declares the JAR to the system as a platform library. This component is important as it helps the system to identify the location of the platform library when it is needed for loading into an application.
The module class ETC
specified in the make file for the XML file is used to place files into the /system/etc
directory of the firmware image.