将十六进制字符串转换为byte []数组有错误" java.lang.StringIndexOutOfBoundsException"

时间:2017-10-03 16:19:43

标签: java android

正如我之前的question (I want to encrypt string on java and decrypt on Android),我仍然没有任何解决方案。

但这对我来说非常重要,所以我尝试以不同的方式思考。我不使用Base64编码/解码,而是使用convert bytesToHex和hexStringToByteArray(This is a reference)

它看起来更好,但是我得到了一个我不理解的错误。

这是我的代码:

//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;
}

加密结果是:

0446CB4A315EED9BE6F5698EAEF87E900A0A0868D0F7C7B1D30A17FBE8AB7D22DEC9E6DB15D70D01C8DA1DD69727D6DA9341844BE84673865F99EDD648FEA5F278FB88956E12D4154C8F7386D61E7118BA6C1AEC72A0EB7CAF187E1DE88D860A9A8A5A2B0526672958C2ABD6360E75649FD9D6457BF410EDC4563B1B10D19590E2C3

这个代码在本地(java - java)或(android - android)中工作得非常好。这意味着如果我在Java程序或Android应用程序上加密/解密本地,它不会有任何错误。

但我想在Java上加密字符串并在Android上解密。这意味着,我将上面的加密字符串复制到Android应用程序并使用此代码解密此字符串:

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;
}

当我这样做时,它有这个错误:

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)

我真的不明白为什么它导致&#34; java.lang.StringIndexOutOfBoundsException&#34;,因为当我在本地Java上使用完全代码块时 - Java / Android - Android它没有那个错误

这对我非常重要。 提前谢谢。

2 个答案:

答案 0 :(得分:1)

看起来这是你的问题

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
如果len是奇数,我会在len-1处获得最大值。 i + 1会= len,因为数组(基本上是字符串是一个字符数组),边界就像你在for循环中一样,(0,len-1)

记住数组的循环边界是正常的,但在进行不等于i的任何数组访问时(即i + 1),请忘记它们

编辑:

一个可能的解决办法可能就是循环

for(int i = 0; i < len-1; i+=2)

答案 1 :(得分:0)

  

java.lang.StringIndexOutOfBoundsException:length = 261 ;指数= 261

为什么是261?您引用的字符串中包含260个字符。检查一些复制粘贴问题,比如某个地方的额外空间。

相关问题