tazeenmulani
tazeenmulani

Reputation: 592

Unable to parse as integer in Android

I want to implement encrypt and decrypt operation for some String values. I have encrypted properly but I don't understand how to decrypt this value like:

jsonString Values ={"Response":"NJGOkF2EvOIpfKG14LHQZrVfj\/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4\/\/uxjDwtZ","statusFlag":"true"}

When I decrypt, I am getting NumberFormatException.

Here is my simple Crypto class

import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;


    public class SimpleCrypto {

            public static String encrypt(String seed, String cleartext) throws Exception {
                    byte[] rawKey = getRawKey(seed.getBytes());
                    byte[] result = encrypt(rawKey, cleartext.getBytes());
                    return toHex(result);
            }

            public static String decrypt(String seed, String encrypted) throws Exception {
                    byte[] rawKey = getRawKey(seed.getBytes());
                    byte[] enc = toByte(encrypted);
                    byte[] result = decrypt(rawKey, enc);
                    return new String(result);
            }

            private static byte[] getRawKey(byte[] seed) throws Exception {
                    KeyGenerator kgen = KeyGenerator.getInstance("AES");
                    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
                    sr.setSeed(seed);
                kgen.init(128, sr); // 192 and 256 bits may not be available
                SecretKey skey = kgen.generateKey();
                byte[] raw = skey.getEncoded();
                return raw;
            }


            private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                    Cipher cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
                byte[] encrypted = cipher.doFinal(clear);
                    return encrypted;
            }

            private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                    Cipher cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.DECRYPT_MODE, skeySpec);
                byte[] decrypted = cipher.doFinal(encrypted);
                    return decrypted;
            }

            public static String toHex(String txt) {
                    return toHex(txt.getBytes());
            }
            public static String fromHex(String hex) {
                    return new String(toByte(hex));
            }

            public static byte[] toByte(String hexString) {
                    int len = hexString.length()/2;
                    byte[] result = new byte[len];
                    for (int i = 0; i < len; i++)
                            result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); //2 * i, 2 * i + 2
                    return result;
            }

            public static String toHex(byte[] buf) {
                    if (buf == null)
                            return "";
                    StringBuffer result = new StringBuffer(2*buf.length);
                    for (int i = 0; i < buf.length; i++) {
                            appendHex(result, buf[i]);
                    }
                    return result.toString();
            }
            private final static String HEX = "0123456789ABCDEF";
            private static void appendHex(StringBuffer sb, byte b) {
                    sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
            }

    }

This is log cat infomation .

01-03 11:30:51.154: W/System.err(437): java.lang.NumberFormatException: unable to parse '{"' as integer
01-03 11:30:51.164: W/System.err(437):  at java.lang.Integer.parse(Integer.java:383)
01-03 11:30:51.164: W/System.err(437):  at java.lang.Integer.parseInt(Integer.java:372)
01-03 11:30:51.164: W/System.err(437):  at java.lang.Integer.valueOf(Integer.java:528)
01-03 11:30:51.164: W/System.err(437):  at com.json_to_server.SimpleCrypto.toByte(SimpleCrypto.java:63)
01-03 11:30:51.164: W/System.err(437):  at com.json_to_server.SimpleCrypto.decrypt(SimpleCrypto.java:20)
01-03 11:30:51.164: W/System.err(437):  at com.json_to_server.EncryptDecrypt_Demo.POST(EncryptDecrypt_Demo.java:202)
01-03 11:30:51.174: W/System.err(437):  at com.json_to_server.EncryptDecrypt_Demo$HttpAsyncTask.doInBackground(EncryptDecrypt_Demo.java:267)
01-03 11:30:51.174: W/System.err(437):  at com.json_to_server.EncryptDecrypt_Demo$HttpAsyncTask.doInBackground(EncryptDecrypt_Demo.java:1)
01-03 11:30:51.174: W/System.err(437):  at android.os.AsyncTask$2.call(AsyncTask.java:185)
01-03 11:30:51.174: W/System.err(437):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
01-03 11:30:51.174: W/System.err(437):  at java.util.concurrent.FutureTask.run(FutureTask.java:138)
01-03 11:30:51.174: W/System.err(437):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
01-03 11:30:51.174: W/System.err(437):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
01-03 11:30:51.174: W/System.err(437):  at java.lang.Thread.run(Thread.java:1019)

And i want to decrypt this value. I don't know where i have to change the code in my SimpleCrypto class

jsonString Values = {"Response":"NJGOkF2EvOIpfKG14LHQZrVfj\/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4\/\/uxjDwtZ","statusFlag":"true"}

Upvotes: 2

Views: 1092

Answers (7)

StoopidDonut
StoopidDonut

Reputation: 8617

Your solution works, the interpretation of the data you are getting is misaligned with what is actually happening.

Your JSON response is not an encrypted byte array but an encoded String. To stream across an array of Bytes (or bits or any binary data for that matter) through a network, it is not generally sent in its raw format. Rather, you want to encode your raw data into characters.

Since your JSON response looks like a stream of characters and not a raw format of bytes, the first assumption I can make is it's an encoded data using one of the most common binary to String encoding - Base64.

The below string (response) is a valid Base64 encoded String, while your decrypt method is expecting the Hex encoded stream of characters.

NJGOkF2EvOIpfKG14LHQZrVfj/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4//uxjDwtZ

Extracting the correct response:

Since JSON 'allows' you to escape front slashes and other escape sequences, your Base64 response needs to be slightly formatted.

I remove the escapes for front slashes and 'escape' the '\' for the line feed (\n). The resulting String looks like (notice \n):

NJGOkF2EvOIpfKG14LHQZrVfj/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4//uxjDwtZ

This is a valid Base64 String, you can test it here (replace \n with a line feed by pressing enter and bringing the rest of the text to the new line).

enter image description here

Notice it downloads a binary file as a result - which proves the the decoded value is in fact a valid binary raw data.

Fixing the code:

As it's evident from NumberFormatException, your decrypt method is expecting a Hex encoded stream of characters which it does not get.

As per your code, the encrypt function would return the Hex encoded value of the String. This is valid as well since Hex is also a representation of binary values in a readable form. However, you might need to level set within your integration to be consistent with the encoding scheme.

Coming back to your algorithm, your decrypt methods expect the encrypted data in Hex form but what you get is a Base64 encoded String.

Aligned to what your logic expects (I didn't want to make changes to your original base code)

  1. We would have to decode the Base64 encoded String - various flavors are available, I used org.apache.commons.codec.binary.Base64 for this test.
  2. Convert it to Hex
  3. Feed it to the decrypt method

The sequences of steps translated like this in the code (within my test class main method):

String encoded = "NJGOkF2EvOIpfKG14LHQZrVfj/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4//uxjDwtZ";

String key = "abc";

String decoded = toHex(Base64.decodeBase64(encoded));
System.out.println(decoded);

String decrypted = decrypt(key, decoded);
System.out.println(decrypted);

Point about your encryption scheme:

Your AES encryption scheme uses a default AES scheme (Cipher.getInstance("AES");) which translates to Cipher.getInstance("AES/ECB/PKCS5Padding"); in SunJCE implementation.

When I run this with a random key abc

javax.crypto.BadPaddingException: Given final block not properly padded

This of course is the scenario of a wrong key as I do not have the key which you would use to encrypt/decrypt your data.

You can test this scenario with the right key and the changes mentioned above, it should work with your current encryption scheme.

My Test case:

As a test case, I disallowed the restraint of padding by replacing your Cipher.getInstance("AES") in decrypt method with

Cipher.getInstance("AES/ECB/NoPadding");

I get a collection of unreadable characters with no exception, which are understandably junk values - reason, again I used a random key which does not align to what you intend to use.

;l:z«1†ŠåÎàÏÙQPÞ—?ñGv’€ò;PöøïÇE1:‰§ŒÔ³

Upvotes: 0

Rajesh Wadhwa
Rajesh Wadhwa

Reputation: 1036

You are using JSON data as string data. you need to pick only the "response" part value of the JSON something like this

JSONObject jO= new JSONObject(value);
String response = jO.getString("Response");

Upvotes: 0

Darshan Patel
Darshan Patel

Reputation: 3256

I think result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); gives you error because your hexstring may contain character literal so Integer.valueOf() function gives you NumberFormatException

for hexstring to byte array conversion please check [link] https://stackoverflow.com/a/140861/3131537

hope that solves your problem

Upvotes: 1

Tapa Save
Tapa Save

Reputation: 4857

You trying parse to Integer string 'NJ' as HEX-digits. But HEX is only 0-9 and A-F symbols. Change your income string to only HEX symbols.

Upvotes: 1

Autocrab
Autocrab

Reputation: 3757

I've tested your class and it's working as i see. Here is my test:

public static void main(String[] args) throws Exception {
   String message = "Some string that i want to encrypt and decrypt";
   String key = "123";

   String encrypted = SimpleCrypto.encrypt(key, message);
   p(encrypted);

   String decrypted = SimpleCrypto.decrypt(key, encrypted);
   p(decrypted);
}

private static void p(String message) {
   System.out.println(message);
} 

and output:

B7498FF642FA8B81289AE8E59E19F081A27B766BE3290617CC15F857BF055DA2668BF81181E26AE2F790968DF39CC070
Some string that i want to encrypt and decrypt

You're getting NumberFormatException because your class decrypts only hexed strings, but this one is not hexed.

Upvotes: 1

Vipul Purohit
Vipul Purohit

Reputation: 9827

I assume you are decrypting the whole JSON string and I think you only need to decrypt

this string : NJGOkF2EvOIpfKG14LHQZrVfj\/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4\/\/uxjDwtZ

So you should parse the JSON and get Response string from JSON and then decrypt it.

UPDATE : You can parse you json string like this :

String value = "YOUR_JSON_STRING";
    try {
        JSONObject mJsonObject = new JSONObject(value);
        String response = mJsonObject.getString("Response");
        //Decrypt response string 

    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Now you have your encrypted string in response variable. Now you can decrypt response string.

Upvotes: 3

johntheripp3r
johntheripp3r

Reputation: 989

You are trying to parse the whole string which containts not only numbers but also text (String). Please review your code and then make this a question

Upvotes: 0

Related Questions