Java 实现RSA加密
目录
介绍生成密钥对RSA 加密RSA 解密RSA 签名RSA 验签测试实例流程
介绍
基于数学难题:RSA 的安全性基于大数分解问题,这在现代计算机上非常困难,特别是对于足够大的密钥长度。破解 RSA 加密需要进行大量的计算,因此 RSA 被认为是一种非常安全的加密方法。
公钥和私钥分开:RSA 使用一对密钥进行加密和解密。公钥可以公开,而私钥必须保密。只有持有私钥的人才能解密使用公钥加密的数据,从而保证了数据的保密性。
生成密钥对
/** * 生成密钥对 * * @return * @throws NoSuchAlgorithmException */ public static String[] generateKeyPair() throws NoSuchAlgorithmException { //始化一个 KeyPairGenerator 对象,用于生成密钥对。 指定RSA 算法 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); // 初始化密钥对生成器,密钥大小为 2048 位。 密钥长度越大,安全性越高,但同时加解密的速度会变慢。 // new SecureRandom() RSA 密钥生成依赖于随机数来保证密钥的不可预测性和安全性。 keyPairGenerator.initialize(2048, new SecureRandom()); KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 获取公钥和私钥 转为Base64 字符串 String pubKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()); String priKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()); return new String[]{pubKey, priKey}; }
RSA 加密
/** * RSA 加密 * * @param message 需要加密的数据 * @param publicKey 公钥字符串 以 Base64 编码的字符串形式传入。 * @return * @throws Exception */ public static String encrypt(String message, String publicKey) throws Exception { //将传入的 Base64 编码的公钥字符串解码为字节数组 byte[] publicBytes = Base64.getDecoder().decode(publicKey); //将解码后的字节数组封装为一个 X509EncodedKeySpec 对象。 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes); //获取一个用于处理 RSA 密钥的工厂实例。 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); //根据提供的公钥规范(keySpec)生成一个实际的 PublicKey 对象,供加密使用。 PublicKey pubKey = keyFactory.generatePublic(keySpec); //指定加密算法为 RSA Cipher cipher = Cipher.getInstance("RSA"); //指定 Cipher 对象的模式为加密模式 使用前面生成的 pubKey 对象来初始化 Cipher 对象。 cipher.init(Cipher.ENCRYPT_MODE, pubKey); //使用 Cipher 对消息进行加密。 byte[] encryptedBytes = cipher.doFinal(message.getBytes()); return Base64.getEncoder().encodeToString(encryptedBytes); }
RSA 解密
/** * RSA 解密 * * @param encryptedMessage 加密字符串 * @param privateKey 私钥字符串 以 Base64 编码的字符串形式传入。 * @return * @throws Exception */ public static String decrypt(String encryptedMessage, String privateKey) throws Exception { //将传入的 Base64 编码的私钥字符串解码为字节数组。 byte[] privateBytes = Base64.getDecoder().decode(privateKey); //将解码后的字节数组封装为一个 PKCS8EncodedKeySpec 对象。 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateBytes); //通过 KeyFactory.getInstance("RSA") 获取一个用于处理 RSA 密钥的工厂实例。 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); //使用 KeyFactory 将 PKCS8EncodedKeySpec 转换为一个 PrivateKey 对象。 供解密使用 PrivateKey priKey = keyFactory.generatePrivate(keySpec); //创建一个 Cipher 实例,指定加密算法为 RSA。 Cipher cipher = Cipher.getInstance("RSA"); //指定 Cipher 对象的模式为解密模式,并使用前面生成的 priKey 对象来初始化 Cipher 对象。 cipher.init(Cipher.DECRYPT_MODE, priKey); //将传入的 Base64 编码的加密消息解码为字节数组。 byte[] encryptedBytes = Base64.getDecoder().decode(encryptedMessage); //加密的字节数组进行解密,返回解密后的字节数组 byte[] decryptedBytes = cipher.doFinal(encryptedBytes); return new String(decryptedBytes); }
RSA 签名
/** * RSA 签名 * * @param message 需要签名的明文消息(字符串) * @param privateKey 私钥字符串 以 Base64 编码的字符串形式传入。 * @return * @throws Exception */ public static String sign(String message, String privateKey) throws Exception { // 将传入的 Base64 编码的私钥字符串解码为字节数组。 byte[] privateBytes = Base64.getDecoder().decode(privateKey); // 将解码后的字节数组封装为 PKCS8EncodedKeySpec 对象。 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateBytes); // 通过 KeyFactory.getInstance("RSA") 获取一个用于处理 RSA 密钥的工厂实例。 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); // 使用 KeyFactory 将 PKCS8EncodedKeySpec 转换为一个 PrivateKey 对象。 供签名使用 PrivateKey priKey = keyFactory.generatePrivate(keySpec); // 创建一个 Signature 实例,指定签名算法为 SHA256withRSA。 SHA256withRSA:指定使用 SHA-256 哈希算法和 RSA 签名算法的组合。 Signature signature = Signature.getInstance("SHA256withRSA"); //使用私钥初始化 Signature 对象,并设置为签名模式。 signature.initSign(priKey); //方法将字节数组添加到签名对象中,以便进行签名。 将消息字符串转换为 UTF-8 编码的字节数组。 signature.update(message.getBytes("UTF-8")); //执行签名操作,返回签名后的字节数组。 byte[] signatureBytes = signature.sign(); //将签名后的字节数组进行 Base64 编码,转换为字符串 return Base64.getEncoder().encodeToString(signatureBytes); }
RSA 验签
/** * RSA 验签 * * @param message 原始消息(字符串),用于与签名进行匹配。 * @param signatureStr 签名的 Base64 编码字符串。 * @param publicKey 公钥的 Base64 编码字符串。 * @return true 表示签名有效,false 表示签名无效 * @throws Exception */ public static boolean verify(String message, String signatureStr, String publicKey) throws Exception { //将传入的 Base64 编码的公钥字符串解码为字节数组。 byte[] publicBytes = Base64.getDecoder().decode(publicKey); //将解码后的字节数组封装为 X509EncodedKeySpec 对象。 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes); //通过 KeyFactory.getInstance("RSA") 获取一个用于处理 RSA 密钥的工厂实例。 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); //使用 KeyFactory 将 X509EncodedKeySpec 转换为一个 PublicKey 对象。 供验签使用 PublicKey pubKey = keyFactory.generatePublic(keySpec); //创建一个 Signature 实例,指定签名算法为 SHA256withRSA。 SHA256withRSA:指定使用 SHA-256 哈希算法和 RSA 签名算法的组合。 Signature signature = Signature.getInstance("SHA256withRSA"); //使用公钥初始化 Signature 对象,并设置为验证模式。 signature.initVerify(pubKey); //将原始消息数据传递给 Signature 对象进行验证。 signature.update(message.getBytes("UTF-8")); //将消息字符串转换为 UTF-8 编码的字节数组。 byte[] signatureBytes = Base64.getDecoder().decode(signatureStr); // 使用 Signature 对象验证签名的有效性。 return signature.verify(signatureBytes); }
测试
public static void main(String[] args) throws Exception { // 生成 RSA 密钥对 String[] strings = generateKeyPair(); String pubKey = strings[0]; String priKey = strings[1]; System.out.println("公钥: " + pubKey); System.out.println("私钥: " + priKey); System.out.println("-------------------------------------------------"); String originalMessage = "Hello, world!"; System.out.println("准备的数据: " + originalMessage); // 加密 String encryptedMessage = encrypt(originalMessage, pubKey); System.out.println("加密数据: " + encryptedMessage); // 解密 String decryptedMessage = decrypt(encryptedMessage, priKey); System.out.println("解密数据: " + decryptedMessage); // 签名 String signature = sign(originalMessage, priKey); System.out.println("签名: " + signature); // 验签 boolean isVerified = verify(originalMessage, signature, pubKey); System.out.println("签名已验证: " + isVerified); }
大家可以把生成的公钥私钥字符串配置在配置文件