Fork me on GitHub

RSA对称加密

RSA

工作原理

  1. 密钥生成:
    • 选择两个大素数 p 和 q ,计算 n = p \times q 。
    • 计算 \phi(n) = (p - 1) \times (q - 1) (欧拉函数)。
    • 选择一个整数 e 满足 1 < e < \phi(n) 且 \gcd(e, \phi(n)) = 1 。
    • 计算 d 使得 e \cdot d \equiv 1 \ (\text{mod} \ \phi(n)) 。
    • 公钥:(e, n),用于加密。
    • 私钥:(d, n),用于解密。
  2. 加密:
    • 将明文 M 转换为数字 m (确保 m < n )。
    • 使用公钥进行加密: c = m^e \mod n 。
  3. 解密:
    • 使用私钥解密: m = c^d \mod n ,还原出明文 M 。
  4. 数字签名:
    • 使用私钥对消息的哈希值进行加密,生成签名。
    • 验签时用公钥解密签名,并与计算出的哈希值进行比较。

优缺点

优点:
• 安全性:基于大整数分解难题,攻击复杂度高。
• 灵活性:支持加密、签名和密钥交换。
• 互操作性:广泛支持,各种协议(如 HTTPS、SSL/TLS)中广泛应用。
缺点:
• 性能较差:比对称加密算法(如 AES)慢得多,通常仅用于加密小数据(如对称密钥)。
• 密钥长度长:安全性依赖于密钥长度,密钥越长性能越低。

RSA 2048 vs 4096

密钥长度
• RSA 的密钥长度指 n 的位数,例如:
• 2048 位密钥: n 是一个约 617 位十进制数。
• 4096 位密钥: n 是一个约 1234 位十进制数。
密钥长度越长,破解的难度越高,但计算性能也会显著下降。

安全性
1. RSA 2048 位:
• 被认为足够安全,可抵抗现有经典计算机的攻击。
• 当前技术下,通过分解 n 破解 RSA 2048 位需要数十亿年的计算。
2. RSA 4096 位:
• 提供更高的安全性,但在实际中很少使用。
• 通常用于高安全性场景,但性能代价较大。

性能比较
1. 加密/解密速度:
• RSA 算法的加解密速度与密钥长度的三次方成正比。
• RSA 2048 位的加解密速度明显快于 RSA 4096 位。
2. 存储需求:
• RSA 4096 位密钥的存储需求约为 RSA 2048 位的两倍。

实际应用建议
1. RSA 2048 位:
• 已成为目前的行业标准,用于绝大多数场景(如 HTTPS、SSL/TLS 等)。
• 安全性足够强,性能表现平衡。
2. RSA 4096 位:
• 用于对安全性有极高要求的场景(如政府、军方、关键基础设施)。
• 在量子计算逐渐成熟的未来可能更有意义,但目前 RSA 2048 已足够安全。

代码

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * RSA对称加密解密工具包
 */
public class RsaEncryptionUtil {

    //公钥 base64加密的公钥
    public final static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsY4RhB9cz9IBt4E73EAYNq2v0Dzc/2GfV/4fqNOefqATD/1HHez1YthpEyA0qKqJbaVTcjetioJJubxgM6edTfOVe5k/TWrt8ykGIQmM0YG+XED1GmMvwjVI+38fLBxbMWMaDRU/2qBcrEMd9VUbyh3q29HIZElNv7vmLLBoi2KswMuMf3Uf/QOlph2NoXvpE24Gq/EmZT+Gn6xFCxkMn6UcCVgsUvkSoETo5hKZhGuZmFrLWZgdhJiIuXFu4J0aCkJ9pQ3Inj1M//mSFtF+i45Xz+2YHIQndcT/5P7B1PLn47AYl0d1aqs0F62/sG6Smg/idfYbL4FF9ANFaa9uTQIDAQAB";
    //私钥 base64加密的私钥
    public final static String PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCxjhGEH1zP0gG3gTvcQBg2ra/QPNz/YZ9X/h+o055+oBMP/Ucd7PVi2GkTIDSoqoltpVNyN62Kgkm5vGAzp51N85V7mT9Nau3zKQYhCYzRgb5cQPUaYy/CNUj7fx8sHFsxYxoNFT/aoFysQx31VRvKHerb0chkSU2/u+YssGiLYqzAy4x/dR/9A6WmHY2he+kTbgar8SZlP4afrEULGQyfpRwJWCxS+RKgROjmEpmEa5mYWstZmB2EmIi5cW7gnRoKQn2lDciePUz/+ZIW0X6LjlfP7ZgchCd1xP/k/sHU8ufjsBiXR3VqqzQXrb+wbpKaD+J19hsvgUX0A0Vpr25NAgMBAAECggEAHb0+/9NE92YkdXkG7rgplhb3aLiZB4lxaAqfgOaZGHp1VutEWyXSYBEBYHu3djzCMgRL+siKn7V85chAkMZVWbYf5ojfincLjfvkE+qGlJzXppoWs6nDWRMVu1IqhXfmalpABcr2XAcaHpxLS0lLE0p5iQIVP37rr96oCfouOJIxpQW5wxmPbp4ei+fwgvJj+1lAhGFOLEFoYFDrG5cy5loYRnrtkSKUUvmMWdWfhQM/jfceBHUdp84JaxZ13p0HfSqO14JVab5CyoT19k6uRaHHrZNU04OJFCH5eswjFL4yB6zeTWM+SEQSAo75Kv0yjcWzgxQYZy9FvE/xW72zAQKBgQDt/SSjaG8wlWimSGtwKmiLJ801kHtLdsv0iA6Xy5CoxptCsNi6KUc8G+1rUINpMktxYFqjYEVwlXzCOWqw7Iy/GHi8x1vFmGW0LXtthCEyLx6MAUFV4ezCeS+VLQxrUBpBnmakf8XSpfM2Qaavb/q5Fh0mipSM5bktcyLaFdD/DQKBgQC+/hBOK1odBHP0GeOMAvvKXxZiMucRcar9ujTcLrX42/ojloFDkKfYfII7M8vW9hq7uOIAeivLxFIb+HAiADd8f+KFRyyjVTxzL7zjx5cTAZkpRYTb/ba/gU4V4VnpWpTQBOYOzPVLdtcMoWopska1va+tmu5cGAVo5vxRxk5cQQKBgQDTsbG9iVAer0h/YTvwcki8P5NSakrCPdH+mmggrnrnJoNFN3oRXlZ3KYBvTRcXpB1npIX7fc9G7jIjsl8tMb2g3mvHwK3pfj45n5uDN10v/qn1b8hmVKj99D5XO9MoQgCZDgXPnbiiP+uv/4X92GX17a3QcsTg8BdgTmJaC730oQKBgG/XROMRfdZqKiByHI57nMhXwDrGxgqv/kpQBO4+qC7PWf4G/zD6f19FIdnbLe119hehXy6aXBUZpF9erwMqD1Pna1VSZXBL1Hc7KChWU0A8+lxxqihMvPwNkxU6/jSo52WcyL84BBgpwipSR2GdVMzOBBbsF9Jz+o8AXBbiwjZBAoGALdubdaeHcnx4l5IxDVwkaZ4rU3l3Qhj2oEGWKVYtP9wVfSMSDTDCDcsb7V1qRwrCJAtBXPcoYg32+LtygoibN/Uyzgr3IrrgTl2oOmMKXnUM69T35wiWljQEURWV2kA1YlbLuHtWmFIeCwOCLqfHneXjm75JDWQcoSxhftBw54M=";

    /**
     * RSA加密
     * @param data 要加密的数据
     * @param publicKeyString base加密的公钥
     * @return base64加密的RSA
     * @throws Exception
     */
    public static String encrypt(String data, String publicKeyString) throws Exception {
        // 解析公钥
        byte[] keyBytes = Base64.getDecoder().decode(publicKeyString);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);

        // 加密数据
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * RSA解密
     * @param encryptedData 已加密数据
     * @param privateKeyString base加密的私钥
     * @return
     * @throws Exception
     */
    public static String decrypt(String encryptedData, String privateKeyString) throws Exception {
        // 解析私钥
        byte[] keyBytes = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        // 解密数据
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        return new String(decryptedBytes);
    }

    /**
     * 生成RSA公钥和私钥
     * @return base64的公钥和私钥
     * @throws Exception
     */
    public static void generateKey() throws Exception {
        try {
            //RSA2048为2048,RSA4096为4096
            int keySize = 2048;
            // 1. 创建 KeyPairGenerator 对象
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            // 2. 初始化密钥大小(通常为 2048 位)
            keyPairGenerator.initialize(keySize);
            // 3. 生成密钥对
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            // 4. 获取公钥和私钥
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();
            // 5. 转换为 Base64 编码的字符串(便于存储或传输)
            String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
            String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
            // 6. 打印公钥和私钥
            System.out.println("Public Key: " + publicKeyString);
            System.out.println("Private Key: " + privateKeyString);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        //生成RSA密钥
        generateKey();

        String data = "Hello, World!";
        String encryptedData = RsaEncryptionUtil.encrypt(data, PUBLIC_KEY);
        String decryptedData = RsaEncryptionUtil.decrypt(encryptedData, PRIVATE_KEY);
        System.out.println("Original Data: " + data);
        System.out.println("Encrypted Data: " + encryptedData);
        System.out.println("Decrypted Data: " + decryptedData);
    }
}
posted @ 2024-12-03 16:26  秋夜雨巷  阅读(31)  评论(0编辑  收藏  举报