RSA加密算法有一个限制,即一次加密的数据长度不能超过密钥长度减去11字节。在默认情况下,2048位RSA密钥的长度为256字节,因此一次最多只能加密245字节的数据。
如果要加密更长的数据,可以使用分段加密的方式。将数据分成若干块,每块的长度不超过密钥长度减去11字节,然后对每块数据进行加密,最后将所有加密后的数据拼接起来。在解密时,也需要将加密后的数据分成若干块进行解密。
创建RSA加密解密工具类
import javax.crypto.Cipher;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* <p>
* Description: RSA加密解密工具类
* </p>
*
* @author songzixian
* @version v2.0.0
* @create 2023-03-12 12:45
* @see com.songzixan.rsa.util
*/
public class RsaUtil {
/**
* 生成RSA公钥和私钥对
* @param algorithm 加密算法,例如"RSA"
* @param keySize 密钥长度,例如2048
* @return 生成的公钥和私钥对
* @throws Exception
*/
public static KeyPair generateKeyPair(String algorithm, int keySize) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
keyPairGenerator.initialize(keySize);
return keyPairGenerator.generateKeyPair();
}
/**
* 将公钥保存到文件中
* @param publicKey 要保存的公钥
* @param fileName 保存到的文件名
* @throws Exception
*/
public static void savePublicKey(PublicKey publicKey, String fileName) throws Exception {
byte[] publicKeyBytes = publicKey.getEncoded();
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(publicKeyBytes);
fos.close();
}
/**
* 将私钥保存到文件中
* @param privateKey 要保存的私钥
* @param fileName 保存到的文件名
* @throws Exception
*/
public static void savePrivateKey(PrivateKey privateKey, String fileName) throws Exception {
byte[] privateKeyBytes = privateKey.getEncoded();
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(privateKeyBytes);
fos.close();
}
/**
* 从文件中加载公钥
* @param fileName 公钥文件名
* @param algorithm 加密算法,例如"RSA"
* @return 加载出的公钥
* @throws Exception
*/
public static PublicKey loadPublicKey(String fileName, String algorithm) throws Exception {
byte[] publicKeyBytes = Files.readAllBytes(Paths.get(fileName));
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePublic(spec);
}
/**
* 从文件中加载私钥
* @param fileName 私钥文件名
* @param algorithm 加密算法,例如"RSA"
* @return 加载出的私钥
* @throws Exception
*/
public static PrivateKey loadPrivateKey(String fileName, String algorithm) throws Exception {
byte[] privateKeyBytes = Files.readAllBytes(Paths.get(fileName));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePrivate(spec);
}
/**
* 加密文件
* @param algorithm 加密算法,例如"RSA"
* @param publicKeyFile 公钥文件名
* @param inputFile 要加密的文件名
* @param outputFile 加密后的文件名
* @throws Exception
*/
public static void encryptFile(String algorithm, String publicKeyFile, String inputFile, String outputFile) throws Exception {
PublicKey publicKey = loadPublicKey(publicKeyFile, algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
byte[] buffer = new byte[245];
int len;
while ((len = fis.read(buffer)) > 0) {
byte[] encrypted = cipher.doFinal(buffer, 0, len);
fos.write(encrypted);
}
fis.close();
fos.flush();
fos.close();
}
/**
* 解密文件
* @param algorithm 加密算法,例如"RSA"
* @param privateKeyFile 私钥文件名
* @param inputFile 要解密的文件名
* @param outputFile 解密后的文件名
* @throws Exception
*/
public static void decryptFile(String algorithm, String privateKeyFile, String inputFile, String outputFile) throws Exception {
PrivateKey privateKey = loadPrivateKey(privateKeyFile, algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
byte[] buffer = new byte[256];
int len;
while ((len = fis.read(buffer)) > 0) {
byte[] decrypted = cipher.doFinal(buffer, 0, len);
fos.write(decrypted);
}
fis.close();
fos.flush();
fos.close();
}
}
创建RSA测试类
import com.songzixan.rsa.util.RsaUtil;
import java.security.*;
/**
* <p>
* Description: RAS文件加密解密测试类
* </p>
*
* @author songzixian
* @version v2.0.0
* @create 2023-03-12 12:47
* @see com.songzixan.rsa.test
*/
public class TestRsa {
public static void main(String[] args) throws Exception {
// 秘钥对
String publicKeyFile = "src/main/resources/public.txt";
String privateKeyFile = "src/main/resources/private.key";
// 需要加密的文件
String inputFile = "src/main/resources/test.txt";
// 解密后的文件
String encryptedFile = "src/main/resources/encrypted.dat";
// 解密后的文件
String decryptedFile = "src/main/resources/decrypted.txt";
// 加密算法
String algorithm = "RSA";
int keySize = 2048;
// 生成公钥和私钥 开发中只需要调一次即可
KeyPair keyPair = RsaUtil.generateKeyPair(algorithm, keySize);
// 保存公钥
RsaUtil.savePublicKey(keyPair.getPublic(), publicKeyFile);
// 保存私钥
RsaUtil.savePrivateKey(keyPair.getPrivate(), privateKeyFile);
// 加密文件
RsaUtil.encryptFile(algorithm, publicKeyFile, inputFile, encryptedFile);
// 解密文件
RsaUtil.decryptFile(algorithm, privateKeyFile, encryptedFile, decryptedFile);
}
}