2

For my previous question, I want to encrypt string on Java and decrypt on Android, I still do not have any solution.

But it is very important to me so I try to think differently. I do not use Base64 encode/decode, instead I use convert bytesToHex and hexStringToByteArray (see this reference).

It looks better, but I got an error I did not understand.

Here is my code:

//encrypt
try {
        Cipher c = Cipher.getInstance("ECIES",BouncyCastleProvider.PROVIDER_NAME);
        c.init(Cipher.ENCRYPT_MODE,publicKey);
        encodeBytes = c.doFinal(origin.getBytes());           
        //encrypt = Base64.getEncoder().encodeToString(encodeBytes);
        encrypt = bytesToHex(encodeBytes);

        System.out.println(encrypt);


    } catch (Exception e) {
        e.printStackTrace();
    }
    //decrypt
    try
    {
        //abc = Base64.getDecoder().decode(encrypt);
        abc = hexStringToByteArray(encrypt);
        Cipher c = Cipher.getInstance("ECIES","BC");
        c.init(Cipher.DECRYPT_MODE,privateKey);
        decodeBytes = c.doFinal(abc);
        String deCrypt = new String(decodeBytes,"UTF-8");

        System.out.println("Decrypt:"+ deCrypt +"\n");
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
public static String bytesToHex(byte[] bytes) 
{
    char[] hexChars = new char[bytes.length * 2];
    for ( int j = 0; j < bytes.length; j++ ) 
    {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}
public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

The encrypt result is:

0446CB4A315EED9BE6F5698EAEF87E900A0A0868D0F7C7B1D30A17FBE8AB7D22DEC9E6DB15D70D01C8DA1DD69727D6DA9341844BE84673865F99EDD648FEA5F278FB88956E12D4154C8F7386D61E7118BA6C1AEC72A0EB7CAF187E1DE88D860A9A8A5A2B0526672958C2ABD6360E75649FD9D6457BF410EDC4563B1B10D19590E2C3

This code work very good in local (java - java) or (android - android). It means if I encrypt/ decrypt local on Java program or Android app, it doesn't have any error.

But I want encrypt string on Java and decrypt on Android. It means, I copy the encrypted string above to android app and use this code to decrypt this string:

Cipher c = Cipher.getInstance("ECIES","SC");
c.init(Cipher.DECRYPT_MODE,privateKeyFromFile);
encodeBytes = hexStringToByteArray(my_encrypted_string);
decodeBytes = c.doFinal(encodeBytes);
String deCrypt = new String(decodeBytes,"UTF-8");

//////////////////And the function//////////////

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

When I do that, it has this error:

10-03 22:54:07.078 19949-19949/com.example.napoleon.luanvana W/System.err: java.lang.StringIndexOutOfBoundsException: length=261; index=261
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at java.lang.String.charAt(Native Method)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at com.example.napoleon.luanvana.MessageFragment.hexStringToByteArray(MessageFragment.java:194)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at com.example.napoleon.luanvana.MessageFragment$3.onClick(MessageFragment.java:156)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at android.view.View.performClick(View.java:6213)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at android.widget.TextView.performClick(TextView.java:11074)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at android.view.View$PerformClick.run(View.java:23645)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at android.os.Handler.handleCallback(Handler.java:751)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at android.os.Looper.loop(Looper.java:154)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6692)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
10-03 22:54:07.079 19949-19949/com.example.napoleon.luanvana W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
10-03 22:54:07.080 19949-19949/com.example.napoleon.luanvana W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)

I do not really understand why it cause "java.lang.StringIndexOutOfBoundsException", because when I use exactly code block on local Java - Java/ Android - Android it not have that error

1 Answer 1

3

It looks like this is your issue

for (int i = 0; i < len; i += 2) {
    data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
            + Character.digit(s.charAt(i+1), 16)); //i+1 goes out of bounds

i maxes out at len-1 if len is odd. i+1 would = len, and because arrays (Essentially what a string is, a char array), the bounds are as you have in your for loop, (0,len-1)

It is very common to remember the proper for loop bounds for arrays, but forget them when doing any array access that isn't equal to i (i.e. i+1)

Edit:

One possible fix could be this for loop

for(int i = 0; i < len-1; i+=2)
Sign up to request clarification or add additional context in comments.

3 Comments

How can I fix it?
Modify the for loop so that i never goes below 0 or above len.
I have to try like your edit, but I have error "org.spongycastle.jcajce.provider.util.BadBlockException: unable to process block". It mean the encrypted string is not true. Like my previous question stackoverflow.com/questions/46536535/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.