对于我之前的问题I want to encrypt string on Java and decrypt on Android,我仍然没有任何解决方案。
但这对我来说非常重要,所以我尝试以不同的方式思考。我不使用 Base64 编码/解码,而是使用 Convert bytesToHex 和 hexStringToByteArray ( see this 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)
我不太明白为什么它会导致“java.lang.StringIndexOutOfBoundsException”,因为当我在本地 Java - Java/Android - Android 上使用确切的代码块时,它不会出现该错误
最佳答案
看来这是你的问题
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 为奇数,则 i 在 len-1 处达到最大值。 i+1 = len,并且因为数组(本质上是字符串,是字符数组),所以边界与 for 循环中的一样,(0,len-1)
记住数组的正确 for 循环边界是很常见的,但在执行任何不等于 i(即 i+1)的数组访问时忘记它们
编辑:
一个可能的修复可能是这个 for 循环
for(int i = 0; i < len-1; i+=2)
关于java - 将十六进制字符串转换为 byte[] 数组时出现错误 "java.lang.StringIndexOutOfBoundsException",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46549160/