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从0到1实现一个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);
}
}