android rsa最大加密明文大小_Android-RSA分段加密解密

本文介绍了Android平台下RSA非对称加密算法的使用,包括如何生成公钥和私钥,以及如何进行分段加密和解密。强调了RSA加密时的最大明文大小限制,如MAX_ENCRYPT_BLOCK为117个字节,解密时的最大密文大小限制为128个字节。提供了完整的Java代码示例,展示了如何利用公钥加密、私钥解密,以及私钥加密、公钥解密的过程。
摘要由CSDN通过智能技术生成

1. RSA 介绍

RSA是一种非对称加密算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个(公钥)加密,则需要用另一个(私钥)才能解密。该算法的理论基于一个数论事实:将两个大素数相乘得出乘积十分容易,但是要对它的乘积进行因式分解却极其困难。

因此可以将乘积公开称为公钥,公钥可以给任何人使用,乘数称为私钥,私钥保密。RSA的安全性依赖于因式分解。在RSA中可以用公钥加密私钥解密,也可以用私钥加密公钥解密。

2. 生成 RSA 公钥和私钥

2.1 使用 Openssl 生成 RSA 公钥和私钥,参考:

2.2 使用Java代码生成 RSA 公钥和私钥:

import android.content.Context;

import android.text.TextUtils;

import android.util.Log;

import java.io.BufferedReader;

import java.io.ByteArrayOutputStream;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.nio.charset.Charset;

import java.nio.charset.StandardCharsets;

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

/**

* RSA 非对称加密算法,加解密工具类,

* 加密长度 不能超过 128 个字节。

*/

public class RSAEncrypt {

public static final String TAG = RSAEncrypt.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;

/**

* 随机生成 RSA 密钥对

*

* @param keyLength 密钥长度,范围:512~2048,一般:1024

*/

public static KeyPair getKeyPair(int keyLength) {

try {

KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_ALGORITHM);

generator.initialize(keyLength);

return generator.genKeyPair();

} catch (Exception e) {

handleException(e);

}

return null;

}

/**

* 获取公钥 Base64 编码

*

* @param publicKey 公钥

*/

public static String getPublicKeyBase64(PublicKey publicKey) {

return DataUtils.base64Encode(publicKey.getEncoded());

}

/**

* 获取私钥 Base64 编码

*

* @param privateKey 公钥

*/

public static String getPrivateKeyBase64(PrivateKey privateKey) {

return DataUtils.base64Encode(privateKey.getEncoded());

}

/**

* 获取 PublicKey 对象

*

* @param pubKey 公钥,X509 格式

*/

public static PublicKey getPublicKey(String pubKey) {

try {

// 将公钥进行 Base64 解码

byte[] publicKey = DataUtils.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 = DataUtils.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);

}

}

2.3 数据工具类

import android.util.Base64;

import java.math.BigInteger;

import java.nio.ByteBuffer;

import java.nio.charset.StandardCharsets;

import java.security.MessageDigest;

import java.util.ArrayList;

/**

* 数据工具类

*/

public class DataUtils {

/**

* 将 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();

}

}

3. RSA 分段加密解密

3.1 公钥加密,私钥解密

/**

* 使用公钥将数据进行分段加密

*

* @param data 要加密的数据

* @param pubKey 公钥 Base64 字符串,X509 格式

* @return 加密后的 Base64 编码数据,加密失败返回 null

*/

public static String encryptByPublicKey(String data, String pubKey) {

try {

byte[] bytes = data.getBytes(CHARSET_UTF8);

// 创建 Cipher 对象

Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);

// 初始化 Cipher 对象,加密模式

cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(pubKey));

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 DataUtils.base64Encode(encryptedData);

} catch (Exception e) {

handleException(e);

}

return null;

}

/**

* 使用私钥将加密后的 Base64 字符串进行分段解密

*

* @param encryptBase64Data 加密后的 Base64 字符串

* @param prvKey 私钥 Base64 字符串,PKCS8 格式

* @return 解密后的明文,解密失败返回 null

*/

public static String decryptByPrivateKey(String encryptBase64Data, String prvKey) {

try {

// 将要解密的数据,进行 Base64 解码

byte[] encryptedData = DataUtils.base64Decode(encryptBase64Data);

// 创建 Cipher 对象,用来解密

Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);

// 初始化 Cipher 对象,解密模式

cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(prvKey));

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;

}

3.2 私钥加密,公钥解密

/**

* 使用 私钥 将数据进行分段加密

*

* @param data 要加密的数据

* @param prvKey 私钥 Base64 字符串,PKCS8 格式

* @return 加密后的 Base64 编码数据,加密失败返回 null

*/

public static String encryptByPrivateKey(String data, String prvKey) {

try {

byte[] bytes = data.getBytes(CHARSET_UTF8);

// 创建 Cipher 对象

Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);

// 初始化 Cipher 对象,加密模式

cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(prvKey));

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 DataUtils.base64Encode(encryptedData);

} catch (Exception e) {

handleException(e);

}

return null;

}

/**

* 使用 公钥 将加密后的 Base64 字符串进行分段解密

*

* @param encryptBase64Data 加密后的 Base64 字符串

* @param pubKey 公钥 Base64 字符串,X509 格式

* @return 解密后的明文,解密失败返回 null

*/

public static String decryptByPublicKey(String encryptBase64Data, String pubKey) {

try {

// 将要解密的数据,进行 Base64 解码

byte[] encryptedData = DataUtils.base64Decode(encryptBase64Data);

// 创建 Cipher 对象,用来解密

Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);

// 初始化 Cipher 对象,解密模式

cipher.init(Cipher.DECRYPT_MODE, getPublicKey(pubKey));

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;

}

3.3 读取安卓 assets 目录下的 RSA 公/私钥

/**

* 读取安卓 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;

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值