RSA String Encryption, security


SDK Version: 
M3

In this tutorial, I show you how to encrypt a string with public key in Android.

First we make a 2048-bit RSA private key in linux:

  1. $ openssl genrsa -out private_key.pem 2048

Then convert private Key to PKCS#8 format, what Java can read: (in Linux)

  1. $ openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt

Then output public key portion in DER format, what Java can read: (in Linux)

  1. $ openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der

Now you have 3 files:
- private_key.pem (you can use this in php to decrypt)
- private_key.der (with this you can decrypt on Android)
- public_key.der (that key use we to encrypt now)

When you have the files, copy public_key.der to the root of your SD-card.
Let’s create encrypt method, that wait for the key path and the string to encode, and return String:

  1.     public String encrypt(String filePath, String original) {
  2.                        
  3.     }

Next create PublicKey object from the public_key file:

  1.         InputStream instream = new FileInputStream(filePath);
  2.         byte[] encodedKey = new byte[instream.available()];
  3.         instream.read(encodedKey);
  4.         X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey);
  5.         KeyFactory kf = KeyFactory.getInstance("RSA");
  6.         PublicKey pkPublic = kf.generatePublic(publicKeySpec);

Now init chiper, than encrypt the string. Encrypted string in byte[]:

  1.                 Cipher pkCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
  2.                 pkCipher.init(Cipher.ENCRYPT_MODE, pkPublic);
  3.                 byte[] encryptedInByte = pkCipher.doFinal(original.getBytes());

Now create a new class next to the Main activity that called Base64Coder. It should look like:

  1. package your.package.name;
  2.  
  3. public class Base64Coder {
  4.  
  5.         private static char[] map1 = new char[64];
  6.         static {
  7.                 int i = 0;
  8.                 for (char c = 'A'; c <= 'Z'; c++)
  9.                         map1[i++] = c;
  10.                 for (char c = 'a'; c <= 'z'; c++)
  11.                         map1[i++] = c;
  12.                 for (char c = '0'; c <= '9'; c++)
  13.                         map1[i++] = c;
  14.                 map1[i++] = '+';
  15.                 map1[i++] = '/';
  16.         }
  17.  
  18.         private static byte[] map2 = new byte[128];
  19.         static {
  20.                 for (int i = 0; i < map2.length; i++)
  21.                         map2[i] = -1;
  22.                 for (int i = 0; i < 64; i++)
  23.                         map2[map1[i]] = (byte) i;
  24.         }
  25.  
  26.         public static String encodeString(String s) {
  27.                 return new String(encode(s.getBytes()));
  28.         }
  29.  
  30.         public static char[] encode(byte[] in) {
  31.                 return encode(in, in.length);
  32.         }
  33.  
  34.         public static char[] encode(byte[] in, int iLen) {
  35.                 int oDataLen = (iLen * 4 + 2) / 3;
  36.                 int oLen = ((iLen + 2) / 3) * 4;
  37.                 char[] out = new char[oLen];
  38.                 int ip = 0;
  39.                 int op = 0;
  40.                 while (ip < iLen) {
  41.                         int i0 = in[ip++] & 0xff;
  42.                         int i1 = ip < iLen ? in[ip++] & 0xff : 0;
  43.                         int i2 = ip < iLen ? in[ip++] & 0xff : 0;
  44.                         int o0 = i0 >>> 2;
  45.                         int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
  46.                         int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
  47.                         int o3 = i2 & 0x3F;
  48.                         out[op++] = map1[o0];
  49.                         out[op++] = map1[o1];
  50.                         out[op] = op < oDataLen ? map1[o2] : '=';
  51.                         op++;
  52.                         out[op] = op < oDataLen ? map1[o3] : '=';
  53.                         op++;
  54.                 }
  55.                 return out;
  56.         }
  57.  
  58.         public static String decodeString(String s) {
  59.                 return new String(decode(s));
  60.         }
  61.  
  62.         public static byte[] decode(String s) {
  63.                 return decode(s.toCharArray());
  64.         }
  65.  
  66.         public static byte[] decode(char[] in) {
  67.                 int iLen = in.length;
  68.                 if (iLen % 4 != 0)
  69.                         throw new IllegalArgumentException(
  70.                                         "Length of Base64 encoded input string is not a multiple of 4.");
  71.                 while (iLen > 0 && in[iLen - 1] == '=')
  72.                         iLen--;
  73.                 int oLen = (iLen * 3) / 4;
  74.                 byte[] out = new byte[oLen];
  75.                 int ip = 0;
  76.                 int op = 0;
  77.                 while (ip < iLen) {
  78.                         int i0 = in[ip++];
  79.                         int i1 = in[ip++];
  80.                         int i2 = ip < iLen ? in[ip++] : 'A';
  81.                         int i3 = ip < iLen ? in[ip++] : 'A';
  82.                         if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
  83.                                 throw new IllegalArgumentException(
  84.                                                 "Illegal character in Base64 encoded data.");
  85.                         int b0 = map2[i0];
  86.                         int b1 = map2[i1];
  87.                         int b2 = map2[i2];
  88.                         int b3 = map2[i3];
  89.                         if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
  90.                                 throw new IllegalArgumentException(
  91.                                                 "Illegal character in Base64 encoded data.");
  92.                         int o0 = (b0 << 2) | (b1 >>> 4);
  93.                         int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
  94.                         int o2 = ((b2 & 3) << 6) | b3;
  95.                         out[op++] = (byte) o0;
  96.                         if (op < oLen)
  97.                                 out[op++] = (byte) o1;
  98.                         if (op < oLen)
  99.                                 out[op++] = (byte) o2;
  100.                 }
  101.                 return out;
  102.         }
  103.  
  104.         private Base64Coder() {
  105.         }
  106.  
  107. }

Now you can convert the encoded byte[] to Base64. From the Base64 create String, and return it:

  1. String encryptedInString = new String(Base64Coder.encode(encryptedInByte));
  2. return encryptedInString;

Also look like this:

  1.     public String encrypt(String filePath, String original) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
  2.        
  3.         InputStream instream = new FileInputStream(filePath);
  4.         byte[] encodedKey = new byte[instream.available()];
  5.         instream.read(encodedKey);
  6.         X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey);
  7.         KeyFactory kf = KeyFactory.getInstance("RSA");
  8.                 PublicKey pkPublic = kf.generatePublic(publicKeySpec);
  9.                
  10.                 Cipher pkCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING&quot;);
  11.                 pkCipher.init(Cipher.ENCRYPT_MODE, pkPublic);
  12.                 byte[] encryptedInByte = pkCipher.doFinal(original.getBytes());
  13.                
  14.                 String encryptedInString = new String(Base64Coder.encode(encryptedInByte));
  15.                
  16.         return encryptedInString;
  17.     }

An example how to use this implemented method:

  1. encrypt("/sdcard/public_key.der&quot;,"text to encrypt");

For example: that encrypted string can you send to a web service, and decrypt with the private_key.pem in PHP