RSA加密算法,加解密、签名验签示例Demo:
package com.example.demo; import javax.crypto.Cipher; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; public class RSAExample { private static final String ALGORITHM = "RSA"; private static final int KEY_SIZE = 2048; private static final String TRANSFORMATION = "RSA/ECB/PKCS1Padding"; // 签名算法(SHA256withRSA是常用的安全组合) private static final String SIGNATURE_ALGORITHM = "SHA256withRSA"; // 生成密钥对 public static KeyPair generateKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM); generator.initialize(KEY_SIZE); return generator.generateKeyPair(); } // 私钥加密 // 私钥加密、公钥解密 从算法上来说是可以的,但与非对称加解密设计相违背 // 在 RSA 中,使用私钥加密在数学上是可行的,但这违背了非对称加密的设计原则和安全最佳实践。 public static String encryptByPrivateKey(PrivateKey privateKey, String data) throws Exception { Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.ENCRYPT_MODE, privateKey); // 用私钥初始化加密模式 byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encrypted); } // 公钥解密 public static String decryptByPublicKey(PublicKey publicKey, String encryptedData) throws Exception { byte[] data = Base64.getDecoder().decode(encryptedData); Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.DECRYPT_MODE, publicKey); // 用公钥初始化解密模式 byte[] decrypted = cipher.doFinal(data); return new String(decrypted, StandardCharsets.UTF_8); } /** * 使用公钥加密数据 * @param publicKey 公钥对象 * @param data 待加密的明文 * @return Base64编码的密文 * @throws Exception 加密过程中可能出现的异常 */ public static String encrypt(PublicKey publicKey, String data) throws Exception { // 获取加密实例 Cipher cipher = Cipher.getInstance(TRANSFORMATION); // 初始化加密模式 cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 执行加密并转为Base64 byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encryptedBytes); } /** * 使用私钥解密数据 * @param privateKey 私钥对象 * @param encryptedData Base64编码的密文 * @return 解密后的明文 * @throws Exception 解密过程中可能出现的异常 */ public static String decrypt(PrivateKey privateKey, String encryptedData) throws Exception { // 获取解密实例 Cipher cipher = Cipher.getInstance(TRANSFORMATION); // 初始化解密模式 cipher.init(Cipher.DECRYPT_MODE, privateKey); // 执行解密 byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); return new String(decryptedBytes, StandardCharsets.UTF_8); } /** * 使用私钥对数据进行签名 * @param privateKey 私钥对象 * @param data 待签名的数据 * @return Base64编码的签名结果 * @throws Exception 签名过程中可能出现的异常 */ public static String sign(PrivateKey privateKey, String data) throws Exception { // 获取签名实例 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); // 用私钥初始化签名器 signature.initSign(privateKey); // 更新待签名的数据 signature.update(data.getBytes(StandardCharsets.UTF_8)); // 生成签名并转为Base64 byte[] signBytes = signature.sign(); return Base64.getEncoder().encodeToString(signBytes); } /** * 使用公钥验证签名 * @param publicKey 公钥对象 * @param data 原始数据 * @param sign 待验证的签名(Base64编码) * @return 验证结果:true-验证通过,false-验证失败 * @throws Exception 验签过程中可能出现的异常 */ public static boolean verify(PublicKey publicKey, String data, String sign) throws Exception { // 获取签名实例 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); // 用公钥初始化验签器 signature.initVerify(publicKey); // 更新原始数据 signature.update(data.getBytes(StandardCharsets.UTF_8)); // 验证签名 byte[] signBytes = Base64.getDecoder().decode(sign); return signature.verify(signBytes); } // 私钥加密、公钥解密 从算法上来说是可以的,但与非对称加解密设计相违背 // 在 RSA 中,使用私钥加密在数学上是可行的,但这违背了非对称加密的设计原则和安全最佳实践。 public static String encryptByKey(Key key, String data) throws Exception{ Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.ENCRYPT_MODE, key); // 初始化加密模式 byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encrypted); } public static String decryptByKey(Key key, String encryptedData) throws Exception { byte[] data = Base64.getDecoder().decode(encryptedData); Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.DECRYPT_MODE, key); // 用公钥初始化解密模式 byte[] decrypted = cipher.doFinal(data); return new String(decrypted, StandardCharsets.UTF_8); } // 密钥格式转换工具方法 public static PublicKey getPublicKey(byte[] bytes) throws Exception { X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes); return KeyFactory.getInstance(ALGORITHM).generatePublic(spec); } public static PrivateKey getPrivateKey(byte[] bytes) throws Exception { PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes); return KeyFactory.getInstance(ALGORITHM).generatePrivate(spec); } public static void main(String[] args) { try { // 1. 生成密钥对 KeyPair keyPair = generateKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); System.out.println("私钥: " + Base64.getEncoder().encodeToString(privateKey.getEncoded())); System.out.println("公钥: " + Base64.getEncoder().encodeToString(publicKey.getEncoded())); System.out.println(); // 2. 原始数据 String original = "======1111用私钥加密的数据"; System.out.println("原始数据: " + original); // 3. 私钥加密 String encrypted = encryptByPrivateKey(privateKey, original); System.out.println("私钥加密: " + encrypted); // 4. 公钥解密 String decrypted = decryptByPublicKey(publicKey, encrypted); System.out.println("公钥解密: " + decrypted); System.out.println(); // String original2 = "======2222用PublicKey加密的数据"; System.out.println("原始数据:" +original2); // 5. 公钥加密 String encrypted2 = encryptByKey(publicKey, original2); System.out.println("公钥加密: " + encrypted2); System.out.println("tkk: " + encryptByKey(publicKey, original2)); // 6. 私钥解密 String decrypted2 = decryptByKey(privateKey, encrypted2); System.out.println("私钥解密: " + decrypted2); String encrypted3 = encrypt(publicKey, original2); System.out.println("公钥加密:" + encrypted3); String decrypted3 = decrypt(privateKey, encrypted3); System.out.println("私钥解密:" + decrypted3); System.out.println("tkk:" + decrypt(privateKey, encrypted2)); // 12. 待签名的数据 String originalData = "这是需要RSA签名的数据,用于验证数据完整性和发送者身份"; System.out.println("\n原始数据: " + originalData); // 13. 使用私钥签名 String signature = sign(privateKey, originalData); System.out.println("签名结果(Base64): " + signature); // 14. 模拟传输后,使用公钥验签(正常情况) boolean verifySuccess = verify(publicKey, originalData, signature); System.out.println("正常数据验签结果: " + (verifySuccess ? "通过" : "失败")); } catch (Exception e) { e.printStackTrace(); } } }