RSA 加密和解密介绍

RSA是一种非对称加密算法,基于大素数乘法的难解性。文章介绍了RSA的加密流程,包括选择大素数p和q,计算公钥和私钥。还讨论了常见的密钥格式如DER、PEM和PKCS#12,以及密钥填充技术如PKCS#1v1.5和OAEP。最后,提供了用Java从零开始和使用内置库实现RSA加密解密的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、RSA加密算法介绍

RSA 是一种非对称加密算法,由三位数学家(Rivest、Shamir 和 Adleman)在 1978 年提出。RSA 加密算法基于一个简单的数论事实:将两个大素数相乘非常容易,但将乘积分解回素数却非常困难。

RSA 加密的流程如下:

  1. 选择两个大素数 p 和 q,并计算它们的乘积 N = p * q。N 称为 RSA 算法的模数,是一个非常大的整数。

  2. 计算欧拉函数 φ(N) = (p-1) * (q-1),其中 φ(N) 表示小于 N 且与 N 互质的正整数的个数。

  3. 选择一个小于 φ(N) 且与 φ(N) 互质的整数 e,作为公钥的指数。e 必须满足 1 < e < φ(N)。

  4. 计算 e 的模 φ(N) 的逆元 d,即满足 e * d ≡ 1 (mod φ(N)) 的整数 d。d 称为私钥的指数。

  5. 公钥是一个有两个值组成的元组 (e, N),私钥是一个有两个值组成的元组 (d, N)。公钥可以公开,私钥必须保密。

  6. 要加密一条消息 M,将 M 转换为一个整数 m,并计算 c ≡ m^e (mod N)。c 称为密文,可以公开发送。

  7. 要解密密文 c,使用私钥的指数 d 计算 m ≡ c^d (mod N)。

RSA 加密算法的安全性基于一个假设:找到 p 和 q 的乘积 N 的质因子分解是一项困难的计算问题。因此,安全性取决于选择足够大的素数 p 和 q,以确保 N 的长度足够大,使得分解 N 成为两个素数的乘积非常困难。

2、常见的秘钥格式

  1. DER 格式:DER (Distinguished Encoding Rules) 是一种二进制格式的编码规则,常用于表示证书、公钥、私钥等。DER 格式的密钥一般使用二进制方式存储,适合在网络传输中使用。

  2. PEM 格式:PEM (Privacy Enhanced Mail) 是一种 ASCII 编码的密钥格式,常用于表示证书、公钥、私钥等。PEM 格式的密钥以"-----BEGIN..."和"-----END..."开头和结尾,中间是 Base64 编码的二进制数据。PEM 格式的密钥便于在文本文件中存储和传输,但不适合直接在网络上传输。

  3. PKCS#12 格式:PKCS#12 是一种由 RSA 实验室开发的二进制格式,用于存储证书和私钥等密钥信息。PKCS#12 格式的文件通常以 .p12 或 .pfx 为后缀名,支持密码保护和加密,可用于在不同的系统之间安全地传输和备份密钥信息。

  4. JKS 格式:JKS (Java KeyStore) 是一种由 Java 语言开发的密钥库格式,用于存储密钥和证书等安全信息。JKS 格式的密钥库使用二进制方式存储,可以在 Java 应用程序中方便地加载和使用。

除了上述常见的密钥格式,还有其他一些格式,如 OpenSSL 的 ENGINE 格式、Microsoft 的 PFX 格式等。在使用密钥时,需要根据具体情况选择合适的密钥格式,并遵循相应的编码规则和安全标准。

3、秘钥的填充方式

在加密和签名过程中,密钥填充是一种重要的技术,用于增加数据的随机性和安全性。密钥填充的作用是将明文数据填充到一个固定大小的数据块中,以满足加密或签名算法的要求。常见的密钥填充方式有以下几种:

  1. PKCS#1 v1.5:是RSA加密标准中最常用的填充方式。它在明文数据前添加一个特定的填充字节序列,以确保每个加密数据块具有相同的大小。

  2. OAEP(Optimal Asymmetric Encryption Padding):是一种更安全的填充方式,适用于RSA、ECC等非对称加密算法。它包含一个伪随机数生成器和一个哈希函数,以确保填充数据的随机性和完整性。

  3. PSS(Probabilistic Signature Scheme):是一种更安全的签名填充方式,适用于RSA、ECC等非对称签名算法。它采用随机数和哈希函数,增加了签名数据的随机性和安全性。

除了上述填充方式,还有一些其他的填充方式,如ISO 9796、ANSI X9.23等,但它们在实际应用中较少使用。

4、用JAVA实现简易RSA加密解密

-----用java从01实现一个message的加密和解密--------

import java.math.BigInteger;

import java.util.Random;

public class RSA {

    private BigInteger p, q, n, phiN, e, d;

    public RSA(int numBits) {

        Random random = new Random();

        p = BigInteger.probablePrime(numBits / 2, random);

        q = BigInteger.probablePrime(numBits / 2, random);

        n = p.multiply(q);

        phiN = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));

        e = BigInteger.valueOf(65537);

        d = e.modInverse(phiN);

    }

    public BigInteger encrypt(BigInteger plaintext) {

        return plaintext.modPow(e, n);

    }

    public BigInteger decrypt(BigInteger ciphertext) {

        return ciphertext.modPow(d, n);

    }

    // 将明文转换为二进制字符串的方法

    public String msgToBigInteger(String message) {

        byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);

        String binaryString = "";

        for (byte b : messageBytes) {

            String binary = Integer.toBinaryString(b & 0xFF);

            binary = String.format("%8s", binary).replace(' ''0');

            binaryString += binary;

        }

        return binaryString;

     }

    

    public static void main(String[] args) {

        RSA rsa = new RSA(1024);

        String binaryString = msgToBigInteger("Hello, world!")

        BigInteger plaintext = new BigInteger(binaryString,2);

        BigInteger ciphertext = rsa.encrypt(plaintext);

        BigInteger decrypted = rsa.decrypt(ciphertext);

        System.out.println("Plaintext: " + plaintext);

        System.out.println("Ciphertext: " + ciphertext);

        System.out.println("Decrypted: " + decrypted);

    }

}

-----使用java库实现一个message的加密和解密--------

import java.math.BigInteger;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.NoSuchAlgorithmException;

import java.security.PrivateKey;

import java.security.PublicKey;

import javax.crypto.Cipher;

public class RSAEncryptionExample {

    public static void main(String[] args) throws Exception {

        // Generate key pair

        KeyPair keyPair = generateKeyPair();

        // Message to be encrypted

        String message = "Hello, world!";

        // Encrypt message using public key

        byte[] encrypted = encrypt(message.getBytes(), keyPair.getPublic());

        // Decrypt message using private key

        byte[] decrypted = decrypt(encrypted, keyPair.getPrivate());

        // Print decrypted message

        System.out.println(new String(decrypted));

    }

    // Generate RSA key pair

    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");

        keyGen.initialize(2048); // Use 2048-bit key size for security

        return keyGen.generateKeyPair();

    }

    // Encrypt data using RSA public key

    public static byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception {

        Cipher cipher = Cipher.getInstance("RSA");

        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        return cipher.doFinal(data);

    }

    // Decrypt data using RSA private key

    public static byte[] decrypt(byte[] data, PrivateKey privateKey) throws Exception {

        Cipher cipher = Cipher.getInstance("RSA");

        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        return cipher.doFinal(data);

    }

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值