登录 |  注册
首页 >  云计算&大数据 >  经典算法大全 · 实例详解 >  RSA非对称加密算法

RSA非对称加密算法

RSA(Rivest-Shamir-Adleman)是一种广泛应用的非对称加密算法,由Ron Rivest、Adi Shamir和Len Adleman在1977年提出。其安全性基于数学上的大数因子分解难题,即对于足够大的两个素数p和q而言,已知它们的乘积很容易,但想要从这个乘积中恢复原始的素数则异常困难。

非对称加密算法传输原理.jpg

RSA算法的使用场景

RSA算法因其非对称加密的特点,在多种信息安全领域有广泛的应用,以下是几个主要的使用场景:

  1. 数据加密:

    1. 密钥交换:RSA常用于安全地交换对称加密算法所需的会话密钥,即通信双方可以通过RSA公钥加密对称密钥,然后对方使用私钥解密得到对称密钥,后续通讯采用更快的对称加密算法(如AES)进行加密和解密。

  2. 数字签名:

    1. 身份验证与完整性校验:RSA可用来创建和验证数字签名,发送者使用自己的私钥对消息摘要进行签名,接收者利用发送者的公钥验证签名,确保消息未被篡改且确实来自声称的发送者。

  3. 身份认证:

    1. SSL/TLS协议:在HTTPS和其他基于SSL/TLS的安全网络协议中,RSA用于服务器和客户端之间的身份认证以及交换对称密钥。

  4. 软件授权和DRM:

    1. 许可证文件加密:软件厂商可以使用RSA加密许可证文件,确保只有持有正确私钥的用户能够解密并激活软件。

  5. PGP/GPG邮件加密:

    1. 端到端加密:在Pretty Good Privacy (PGP) 或GNU Privacy Guard (GPG) 中,RSA用于加密电子邮件和其他数据的密钥,实现安全的端到端通信。

  6. 移动支付与电子商务:

    1. 信用卡交易:在线支付系统中,RSA用于保护信用卡信息和其他敏感数据的传输。

  7. SSH远程登录:

    1. 用户身份验证:在Secure Shell (SSH) 登录过程中,RSA或类似非对称加密算法用于生成和验证用户的身份密钥。

总之,RSA算法在任何需要保证数据安全性和完整性的场合中都是不可或缺的工具,特别是在那些要求信任链传递、防止中间人攻击或者维护不可抵赖性的场景中。

RSA算法的基本流程如下:

公私钥加解密.jpg

1.密钥生成:

  • 选择两个大素数 p 和 q。

  • 计算 模数 n = p * q。

  • 计算欧拉函数值 Φ(n) = (p-1) * (q-1)。

  • 选择一个相对较小的整数 e,满足 1 < e < Φ(n) 且 gcd(e, Φ(n)) = 1,即 e 和 Φ(n) 互质。

  • 计算 秘钥 d,使得 d * e ≡ 1 (mod Φ(n)),这通常通过扩展欧几里得算法来完成。

  • 公钥为 (n, e),私钥为 (n, d)。

2.加密:

  • 假设A要向B发送一条消息 m,B已将其公钥 (n, e) 发送给A。

  • 加密过程:ciphertext = m^e mod n,其中 ^ 表示幂运算。

3.解密:

  • B收到密文后,使用自己的私钥 (n, d) 进行解密:plaintext = ciphertext^d mod n。

RSA常用于数字签名、密钥交换等场景,由于非对称加密的特性,一方可以用公钥加密数据,只有拥有相应私钥的一方才能解密。然而,由于性能原因,RSA并不适合大量数据的直接加密,通常的做法是仅用RSA加密对称加密算法的密钥,然后使用对称加密算法加密实际的数据内容。

RSA加密算法java代码示例

RSA加密算法在Java中的实现通常涉及生成密钥对、加密与解密操作。以下是一个简单的RSA加密和解密的Java代码示例:

import java.security.*;
import javax.crypto.Cipher;
import java.util.Base64;

public class RSACoder {
    private static final String ALGORITHM = "RSA";

    /**
     * 生成密钥对
     */
    public static Map<String, Object> generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGen.initialize(2048); // 生成2048位的密钥对
        KeyPair keyPair = keyPairGen.generateKeyPair();
        
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        
        // 将密钥转换为字符串
        String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        
        Map<String, Object> keyMap = new HashMap<>();
        keyMap.put("publicKey", publicKeyStr);
        keyMap.put("privateKey", privateKeyStr);

        return keyMap;
    }

    /**
     * 使用公钥加密
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKeyStr) throws Exception {
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);

        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        return cipher.doFinal(data);
    }

    /**
     * 使用私钥解密
     */
    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKeyStr) throws Exception {
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyStr));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);

        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        return cipher.doFinal(encryptedData);
    }
    
    // 示例用法
    public static void main(String[] args) throws Exception {
        Map<String, Object> keyMap = generateKeyPair();
        String publicKeyStr = (String) keyMap.get("publicKey");
        String privateKeyStr = (String) keyMap.get("privateKey");

        // 假设要加密的数据
        String plainText = "Hello, RSA!";
        byte[] plainBytes = plainText.getBytes("UTF-8");

        // 公钥加密
        byte[] encryptedBytes = encryptByPublicKey(plainBytes, publicKeyStr);

        // 私钥解密
        byte[] decryptedBytes = decryptByPrivateKey(encryptedBytes, privateKeyStr);
        String decryptedText = new String(decryptedBytes, "UTF-8");

        System.out.println("原文: " + plainText);
        System.out.println("解密后: " + decryptedText);
    }
}

这段代码首先定义了一个RSACoder类,包含生成密钥对的方法generateKeyPair(),以及使用公钥加密encryptByPublicKey()和私钥解密decryptByPrivateKey()的方法。在主方法中,它展示了如何生成密钥对,然后使用公钥加密一段文本,并使用相应的私钥解密回去。

注意在实际项目中,可能还需要处理Base64编码后的密钥字符串,以及处理加密和解密过程中可能出现的异常。此外,RSA加密的数据块大小有限制,超过这个限制需要进行合适的填充处理,例如使用OAEP或PKCS#1 v1.5等模式。


上一篇: AES加密算法(对称加密算法)
下一篇: CRC循环冗余校验(Cyclic Redundancy Check,CRC)
推荐文章
  • MD5(Message-DigestAlgorithm5)是一种广泛使用的散列函数(哈希函数),由美国密码学家罗纳德·李维斯特(RonaldL.Rivest)在1991年设计。MD5的作用是对任意长度的信息生成一个固定长度(128位,即32个十六进制字符)的“指纹”或“消息摘要”,并且几乎不可能找到
  • 循环冗余校验(CyclicRedundancyCheck,CRC)是一种用于检测数据传输和存储过程中发生错误的技术,属于一种基于数学原理的错误检测编码(ErrorDetectionCoding)方法。它通过在原始数据上附加一个固定长度的校验码,使得接收端可以通过同样的计算规则对收到的数据进行校验,确
  • AES(AdvancedEncryptionStandard)是一种广泛使用的对称密钥加密算法,它是美国国家标准与技术研究院(NIST)于2001年制定的加密标准,用于替代原有的DES(DataEncryptionStandard)。AES算法以其高效性、安全性和可靠性而著称,在众多应用领域中被广泛
  • RSA(Rivest-Shamir-Adleman)是一种广泛应用的非对称加密算法,由RonRivest、AdiShamir和LenAdleman在1977年提出。其安全性基于数学上的大数因子分解难题,即对于足够大的两个素数p和q而言,已知它们的乘积很容易,但想要从这个乘积中恢复原始的素数则异常困难
  • 最小生成树(MinimumSpanningTree,MST)是一种图论算法,用于在一个带权重的无向连通图中找到一棵包括所有顶点且总权重尽可能小的树。常见的最小生成树算法有两种:Prim算法和Kruskal算法。Prim算法原理:Prim算法是一种贪心算法,它从图中的一个顶点开始,逐步增加边,每次都添
  • 关于最短路径算法的Java实现,这里简述一下几种常用的算法及其基本原理,并给出一个Dijkstra算法的基本实现框架。Dijkstra算法(适用于无负权边的图)Dijkstra算法用于寻找图中一个顶点到其他所有顶点的最短路径。它维护了一个距离表,用来存储从源点到各个顶点的已知最短距离,并且每次都会选
学习大纲