Caused by: java.lang.ArrayIndexOutOfBoundsException: too much data for RSA block

本文介绍了解决RSA加密过程中出现的数据过大导致的解密失败问题。通过在加密后使用Base64编码,并在解密前进行Base64解码的方式,成功解决了这一常见问题。

   前一阵子做应用内秘钥加密,用得RSA,加密没有问题,但是在解密阶段,直接就报错,关键的错误就是标题的这个错误。

不明白为什么测试的时候没有问题,但是正是运行的时候有问题,认真看了一下报错,是说需要解密的RSA数据太大了。。其实解决方式很简单,就是在加密的时候对已经RSA加密的数据进行Base64加密,然后解密的时候先进行Base64解密,然后进行RSA解密。废话不多说,上RSAUtil关键代码

package com.sunsy.demoproject.util;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import sun.misc.BASE64Decoder;

public class RSAUtil {

    /**
     * 从字符串中加载公钥
     *
     * @param publicKeyStr 公钥数据字符串
     * @throws Exception 加载公钥时产生的异常
     */
    public static RSAPublicKey loadPublicKey(String publicKeyStr) throws Exception {
        try {
            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("公钥非法");
        } catch (IOException e) {
            throw new Exception("公钥数据内容读取错误");
        } catch (NullPointerException e) {
            throw new Exception("公钥数据为空");
        }
    }

    public static RSAPrivateKey loadPrivateKey(String privateKeyStr) throws Exception {
        try {
            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("私钥非法");
        } catch (IOException e) {
            throw new Exception("私钥数据内容读取错误");
        } catch (NullPointerException e) {
            throw new Exception("私钥数据为空");
        }
    }


    /**
     * 加密
     *
     * @param publicKey
     * @param srcBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public static byte[] encrypt(RSAPublicKey publicKey, byte[] srcBytes) {
        try {
            if (publicKey != null) {
                //Cipher负责完成加密或解密工作,基于RSA
                Cipher cipher = Cipher.getInstance("RSA");
                //根据公钥,对Cipher对象进行初始化
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                byte[] resultBytes = cipher.doFinal(srcBytes);
                return resultBytes;
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密
     *
     * @param privateKey
     * @param srcBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public static byte[] decrypt(RSAPrivateKey privateKey, byte[] srcBytes) {
        try {
            if (privateKey != null) {
                //Cipher负责完成加密或解密工作,基于RSA
                Cipher cipher = Cipher.getInstance("RSA");
                //根据公钥,对Cipher对象进行初始化
                cipher.init(Cipher.DECRYPT_MODE, privateKey);
                byte[] resultBytes = cipher.doFinal(srcBytes);
                return resultBytes;
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return null;
    }
}

上面这个就是RSA加密,解密工具类。你可以自己生成公钥,私钥进行测试。

先说我引起错误的代码

package com.sunsy.demoproject.activity

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Base64
import android.view.View
import com.starv.recommend.utils.PreContact
import com.starv.recommend.utils.PreUtil
import com.sunsy.demoproject.R
import com.sunsy.demoproject.config.Config
import com.sunsy.demoproject.util.RSAUtil
import kotlinx.android.synthetic.main.ac_main.*

class MainAc : AppCompatActivity() {

    private var originSign = "R++ihY0MA1wPfhVu5R2qW5XLx8OJSoXyC8m55CZOKTY=";

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.ac_main)
    }

    /**
     * 解密
     */
    fun decode(view: View) {
        var rsaSign = PreUtil.getInstance().getString(PreContact.SIGN)
//        String(RSAUtil.decrypt(RSAUtil.loadPrivateKey(Config.PRIVATEKEY), Base64.decode(rsaSign, Base64.DEFAULT)))
        tv_decode.text = String(RSAUtil.decrypt(RSAUtil.loadPrivateKey(Config.PRIVATEKEY), rsaSign.toByteArray()))
    }

    /**
     * 加密
     */
    fun encode(view: View) {
        var rsaSign = RSAUtil.encrypt(RSAUtil.loadPublicKey(Config.PUBLICKEY), originSign.toByteArray())
//        PreUtil.getInstance().putString(PreContact.SIGN, Base64.encodeToString(RSASign, Base64.DEFAULT))
        PreUtil.getInstance().putString(PreContact.SIGN, String(rsaSign))
        tv_encode.text = String(rsaSign)
    }

}
解决方案就是把我注释的代码放开,注释掉下面的那个就可以。
Java中`ArrayIndexOutOfBoundsException: 16135`错误属于`ArrayIndexOutOfBoundsException`(数组越界异常),这是一种常见的运行时异常,通常发生在尝试访问数组中不存在的索引时。在Java里,数组是固定大小的数据结构,每个元素通过索引访问,若尝试访问的索引超出数组实际范围(小于0或大于等于数组长度),就会抛出该异常 [^2]。 要解决`ArrayIndexOutOfBoundsException: 16135`错误,可从以下方面着手: 1. **检查数组初始化**:保证数组已正确初始化,且有足够的长度来容纳要访问的索引。例如: ```java int[] array = new int[20000]; // 确保数组长度足够 ``` 2. **检查索引计算**:查看代码里索引的计算逻辑,保证计算出的索引在数组有效范围内。例如: ```java int index = someCalculation(); // 确保 someCalculation() 返回的索引在数组范围内 if (index >= 0 && index < array.length) { int value = array[index]; } else { // 处理索引越界的情况 System.out.println("索引越界,无法访问数组元素。"); } ``` 3. **调试输出**:在代码里添加调试输出语句,打印出数组长度和要访问的索引,从而确认问题所在。例如: ```java int[] array = new int[100]; int index = 16135; System.out.println("数组长度: " + array.length); System.out.println("要访问的索引: " + index); if (index >= 0 && index < array.length) { int value = array[index]; } else { System.out.println("索引越界,无法访问数组元素。"); } ``` 4. **使用循环时注意边界条件**:在使用循环遍历数组时,要确保循环条件不会导致索引越界。例如: ```java int[] array = new int[100]; for (int i = 0; i < array.length; i++) { // 确保循环条件不会越界 // 处理数组元素 } ```
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值