Android使用RSA分段加解密

RSA为非对称加密,加解密用一对秘钥(公钥,私钥)

  • 公钥和私钥成对出现,是相对的,没有规定哪个必须是公钥哪个必须是私钥
  • 用公钥加密的数据只有对应的私钥可以解密
  • 用私钥加密的数据只有对应的公钥可以解密
  • 如果可以用公钥解密,则必然是对应的私钥加的密
  • 如果可以用私钥解密,则必然是对应的公钥加的密

在GitLab配置SSH的时候的密钥格式

RSA加密解密的时候正确秘钥格式:

MIICWwIBAAKBgQCVJMZF3H7+u4HuYHRwUwc0VXUcuG77PHHSnoKzNHCt/L0W+MnY
u+IB9Qf5nGlxSkL7mSEmn/4neazAMS3Qro0Lu4juEs96C7GWLn/yWdhMcuvzYnmc
zUKzaIOnqJEbcb/JstwMuHCmOwzK3sQvYVyJQEY5ZIkQyBRe595nifQKnwIDAQAB
AoGANb0ga/+9CpAJixjaG7bu+55nKkgSRRhMcvWGZofYqfhNMb/HCv73unjNvNTs
8VMuu3U7iq1PaG3hHwcZWP3r9+d0jsgfEfWzGin2weu8yMVvNtIj/AleHwaLbi8A
L77TIiRsme+1WfZwz8SiJE2+Jof4MvmCoG5UHa1QqgHJnXECQQDD3LvD82hFs3JF
V44PNnF/dREtGp6373NkL49KKTf2o0mBHoC3GErcMhO5FSa8HCKwToHmZOQMEPja
bdjPM1eFAkEAwu/XiiPWDX0XFcqICjUMmb6Es2ZtcwiHie2pSXT5+dVZ+UAn2j0K
hTkjdH+8LJYFJMN/A57PH2XbVj6LXSfI0wJATn3vYZ/ycbxwVwm3jLEs2v93WrQI
V35GqCfHLNlH7DeUBYLL4pSBq60F6m5nj4tW+4D63fIg0hUbJa5P7PmOYQJAGYPP
EHO0Vruiw+VofP2Ikq8PK3Qiq0XYh8Mlv0miVoMIbclp7fTDZcCe1WbKuINCVReJ
jm3A6nkohldVYnIMpQJACduMPIr1tAkOyy+zK4oPfsrFTY6/YhnQ5NH3mQp/ETDl
N9Fa2BS04hu4+sA85LESYz7tLewqyJ9RUBJwmnxstw==


RSA加密解密的时候错误秘钥格式:

-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCVJMZF3H7+u4HuYHRwUwc0VXUcuG77PHHSnoKzNHCt/L0W+MnY
u+IB9Qf5nGlxSkL7mSEmn/4neazAMS3Qro0Lu4juEs96C7GWLn/yWdhMcuvzYnmc
zUKzaIOnqJEbcb/JstwMuHCmOwzK3sQvYVyJQEY5ZIkQyBRe595nifQKnwIDAQAB
AoGANb0ga/+9CpAJixjaG7bu+55nKkgSRRhMcvWGZofYqfhNMb/HCv73unjNvNTs
8VMuu3U7iq1PaG3hHwcZWP3r9+d0jsgfEfWzGin2weu8yMVvNtIj/AleHwaLbi8A
L77TIiRsme+1WfZwz8SiJE2+Jof4MvmCoG5UHa1QqgHJnXECQQDD3LvD82hFs3JF
V44PNnF/dREtGp6373NkL49KKTf2o0mBHoC3GErcMhO5FSa8HCKwToHmZOQMEPja
bdjPM1eFAkEAwu/XiiPWDX0XFcqICjUMmb6Es2ZtcwiHie2pSXT5+dVZ+UAn2j0K
hTkjdH+8LJYFJMN/A57PH2XbVj6LXSfI0wJATn3vYZ/ycbxwVwm3jLEs2v93WrQI
V35GqCfHLNlH7DeUBYLL4pSBq60F6m5nj4tW+4D63fIg0hUbJa5P7PmOYQJAGYPP
EHO0Vruiw+VofP2Ikq8PK3Qiq0XYh8Mlv0miVoMIbclp7fTDZcCe1WbKuINCVReJ
jm3A6nkohldVYnIMpQJACduMPIr1tAkOyy+zK4oPfsrFTY6/YhnQ5NH3mQp/ETDl
N9Fa2BS04hu4+sA85LESYz7tLewqyJ9RUBJwmnxstw==
-----END RSA PRIVATE KEY-----

1、秘钥生成

  • 安装openssl,配置好环境变量后,win+R输入cmd点击确定,进入windows 命令行窗口输入openssl,进入Openssl 程序

  • 输入命令: genrsa -out pkcs1_rsa_private_key.pem 1024          生成 RSA 私钥。

  • 输入命令: rsa -in pkcs1_rsa_private_key.pem -pubout -out pkcs1_rsa_public_key.pem          使用 RSA 私钥生成 RSA 公钥

  • 因为 Java 不支持使用 PKCS1 格式的公钥和私钥,所以要对私钥进行 PKCS8 编码才能在 Java 中使用

  • 输入命令: pkcs8 -topk8 -in pkcs1_rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt          对私钥进行 PKCS8 编码

  • 输入命令:rsa -in pkcs8_rsa_private_key.pem -pubout -out pkcs8_rsa_public_key.pem          使用 PKCS8 编码后的私钥重新生成 RSA 公钥

  • pkcs8_rsa_private_key.pem 和 pkcs8_rsa_public_key.pem 文件可以直接在 Java 中进行 RSA 加解密(就是我们需要的公钥和私钥)。

  • 生成的秘钥一般在     系统盘:\Users\用户名     下

2、Android工程中秘钥存放位置 

3、RSA工具类

/**
 * RSA 非对称加密算法,加解密工具类,
 * 加密长度 不能超过 128 个字节。
 */
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public class RSA {

    public static final String TAG = RSA.class.getSimpleName() + " --> ";

    /**
     * 编码
     */
    public static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;

    /**
     * 标准 jdk 加密填充方式,加解密算法/工作模式/填充方式
     */
    public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";

    /**
     * RSA 加密算法
     */
    public static final String KEY_ALGORITHM = "RSA";

    /**
     * RSA 最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /**
     * 获取 PublicKey 对象
     *
     * @param pubKey 公钥,X509 格式
     */
    public static PublicKey getPublicKey(String pubKey) {
        try {
            // 将公钥进行 Base64 解码
            byte[] publicKey = base64Decode(pubKey);
            // 创建 PublicKey 对象并返回
            return KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(
                    new X509EncodedKeySpec(publicKey));
        } catch (Exception e) {
            handleException(e);
        }
        return null;
    }

    /**
     * 获取 PrivateKey 对象
     *
     * @param prvKey 私钥,PKCS8 格式
     */
    public static PrivateKey getPrivateKey(String prvKey) {
        try {
            // 私钥数据
            byte[] privateKey =base64Decode(prvKey);
            // 创建 PrivateKey 对象并返回
            return KeyFactory.getInstance(KEY_ALGORITHM)
                    .generatePrivate(new PKCS8EncodedKeySpec(privateKey));
        } catch (Exception e) {
            handleException(e);
        }
        return null;
    }

    /**
     * 处理异常
     */
    private static void handleException(Exception e) {
        e.printStackTrace();
        Log.e(TAG, TAG + e);
    }
    /**
     * 使用公钥将数据进行分段加密
     *
     * @param data   要加密的数据
     * @return 加密后的 Base64 编码数据,加密失败返回 null
     */
    public static String encryptByPublicKey(Context context,String data) {
        try {
            byte[] bytes = data.getBytes(CHARSET_UTF8);
            // 创建 Cipher 对象
            Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
            // 初始化 Cipher 对象,加密模式
            cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(getRSAKeyFromAssets(context,"pkcs8_rsa_public_key.pem")));
            int inputLen = bytes.length;
            // 保存加密的数据
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0, i = 0;
            byte[] cache;
            // 使用 RSA 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(bytes, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(bytes, offSet, inputLen - offSet);
                }
                // 将加密以后的数据保存到内存
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            // 将加密后的数据转换成 Base64 字符串
            return base64Encode(encryptedData);
        } catch (Exception e) {
            handleException(e);
        }
        return null;
    }

    /**
     * 使用私钥将加密后的 Base64 字符串进行分段解密
     *
     * @param encryptBase64Data 加密后的 Base64 字符串
     * @return 解密后的明文,解密失败返回 null
     */
    public static String decryptByPrivateKey(Context context,String encryptBase64Data) {
        try {
            // 将要解密的数据,进行 Base64 解码
            byte[] encryptedData = base64Decode(encryptBase64Data);
            // 创建 Cipher 对象,用来解密
            Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
            // 初始化 Cipher 对象,解密模式
            cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(getRSAKeyFromAssets(context,"pkcs8_rsa_private_key.pem")));
            int inputLen = encryptedData.length;
            // 保存解密的数据
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0, i = 0;
            byte[] cache;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                // 将解密后的数据保存到内存
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return new String(decryptedData, CHARSET_UTF8);
        } catch (Exception e) {
            handleException(e);
        }
        return null;
    }

    /**
     * 使用 私钥 将数据进行分段加密
     *
     * @param data   要加密的数据
     * @return 加密后的 Base64 编码数据,加密失败返回 null
     */
    public static String encryptByPrivateKey(Context context,String data) {
        try {
            byte[] bytes = data.getBytes(CHARSET_UTF8);
            // 创建 Cipher 对象
            Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
            // 初始化 Cipher 对象,加密模式
            cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(getRSAKeyFromAssets(context,"pkcs8_rsa_private_key.pem")));
            int inputLen = bytes.length;
            // 保存加密的数据
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0, i = 0;
            byte[] cache;
            // 使用 RSA 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(bytes, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(bytes, offSet, inputLen - offSet);
                }
                // 将加密以后的数据保存到内存
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            // 将加密后的数据转换成 Base64 字符串
            return base64Encode(encryptedData);
        } catch (Exception e) {
            handleException(e);
        }
        return null;
    }

    /**
     * 使用 公钥 将加密后的 Base64 字符串进行分段解密
     *
     * @param encryptBase64Data 加密后的 Base64 字符串
     * @return 解密后的明文,解密失败返回 null
     */
    public static String decryptByPublicKey(Context context,String encryptBase64Data) {
        try {
            // 将要解密的数据,进行 Base64 解码
            byte[] encryptedData = base64Decode(encryptBase64Data);
            // 创建 Cipher 对象,用来解密
            Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
            // 初始化 Cipher 对象,解密模式
            cipher.init(Cipher.DECRYPT_MODE, getPublicKey(getRSAKeyFromAssets(context,"pkcs8_rsa_public_key.pem")));
            int inputLen = encryptedData.length;
            // 保存解密的数据
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0, i = 0;
            byte[] cache;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                // 将解密后的数据保存到内存
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return new String(decryptedData, CHARSET_UTF8);
        } catch (Exception e) {
            handleException(e);
        }
        return null;
    }
    /**
     * 读取安卓 assets 目录下的 RSA 公/私钥
     */
    public static String getRSAKeyFromAssets(Context context, String fileName) {
        try {
            if (TextUtils.isEmpty(fileName)) return null;
            // 打开 assets 目录下的文件
            InputStream in = context.getAssets().open(fileName);
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder builder = new StringBuilder();
            String line;
            // 每次读取一行
            while ((line = reader.readLine()) != null) {
                if (line.charAt(0) != '-') {
                    builder.append(line).append('\r');
                }
            }
            reader.close();
            in.close();
            return builder.toString();
        } catch (Exception e) {
            handleException(e);
        }
        return null;
    }
    /**
     * 将 Base64 字符串 解码成 字节数组
     */
    public static byte[] base64Decode(String data) {
        return Base64.decode(data, Base64.NO_WRAP);
    }

    /**
     * 将 字节数组 转换成 Base64 编码
     */
    public static String base64Encode(byte[] data) {
        return Base64.encodeToString(data, Base64.NO_WRAP);
    }

    /**
     * 将字节数组转换成 int 类型
     */
    public static int byte2Int(byte[] bytes) {
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        return buffer.getInt();
    }

    /**
     * 将 int 转换成 byte 数组
     */
    public static byte[] int2byte(int data) {
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.putInt(data);
        return buffer.array();
    }
}

4、使用

public class MainActivity extends AppCompatActivity {
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String str=RSA.encryptByPublicKey(this,"你好");
        Log.i("-=-=加密",str);
        Log.i("-=-=解密", RSA.decryptByPrivateKey(this,str));
    }
}

参考:

Android-RSA分段加密解密 - 简书

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
非常感谢您的提问。关于Java RSA分段加解密,我可以给您提供一些相关的信息和代码示例。RSA是一种非对称加密算法,可以实现安全的数据传输和数据存储。但是,RSA算法在处理大量数据时可能会出现性能问题。因此,我们需要将大块数据分成小块进行加密和解密。以下是Java RSA分段加解密的代码示例: ``` // RSA密钥长度,推荐使用2048位及以上 private static final int RSA_KEY_SIZE = 2048; // 分段加密的块大小,推荐使用RSA密钥长度-11 private static final int BLOCK_SIZE = RSA_KEY_SIZE / 8 - 11; // 生成RSA密钥对 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(RSA_KEY_SIZE); KeyPair keyPair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); // 分段加密 public static byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] block; int i = 0; while (inputLen - offSet > 0) { if (inputLen - offSet > BLOCK_SIZE) { block = cipher.doFinal(data, offSet, BLOCK_SIZE); } else { block = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(block, 0, block.length); i++; offSet = i * BLOCK_SIZE; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } // 分段解密 public static byte[] decrypt(byte[] encryptedData, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] block; int i = 0; while (inputLen - offSet > 0) { if (inputLen - offSet > RSA_KEY_SIZE / 8) { block = cipher.doFinal(encryptedData, offSet, RSA_KEY_SIZE / 8); } else { block = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(block, 0, block.length); i++; offSet = i * (RSA_KEY_SIZE / 8); } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } ``` 通过以上代码示例,您可以实现Java RSA分段加解密。请注意,RSA算法只适合加密小块数据,不适合加密大块数据,否则可能会出现性能问题。如果您需要加密大块数据,可以考虑使用对称加密算法,如AES。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值