RSA算法基本概念及其使用
RSA 是一种非对称加密算法,广泛应用于网络安全领域,用于加密、签名和密钥交换等场景。RSA 算法的核心思想是利用数学上的难题,如大质数分解问题和欧拉函数等,构建一个公钥和私钥的加密系统,其中公钥用于加密,私钥用于解密.RSA 算法的安全性取决于大素数 p 和 q 的选取(p,q在算法实现流程中有涉及),以及密钥长度的选择。一般来说,为了保证 RSA 加密算法的安全性,密钥长度应该选择 2048 比特或更长的长度。此外,为了防止一些攻击,如 RSA 公钥加密填充攻击,还需要对加密和解密过程中的填充方式进行选择和处理。
算法的实现流程:
- 1.选择两个大素数 p 和 q,计算它们的乘积 n=p*q,n 称为模数。
- 2.计算欧拉函数 φ(n)=(p-1)*(q-1),φ(n) 表示小于 n 的正整数中与 n 互质的数的个数。
- 3.选择一个整数 e,1<e<φ(n),且 e 和 φ(n) 互质,e 称为公钥指数。
- 4.计算 e 的模 φ(n) 的乘法逆元 d,即满足 e * d ≡ 1 (mod φ(n)) 的最小正整数 d,d 称为私钥指数。
- 5 .公钥是 (n,e),私钥是 (n,d)。
- 6.加密:将明文 m 转换为整数 M,0<=M<n,然后计算密文 C=M^e mod n。
- 7 .解密:将密文 C 转换为整数,然后计算明文 M=C^d mod n。
常见的RSA算法及其填充模式的优缺点
- 1.RSA(“RSA”):
- 优点:这是最常用的RSA加密算法,支持多种填充模式,比较通用。
- 缺点:如果使用错误的填充模式,可能会导致安全漏洞。
- 2.RSA_ECB_PKCS1(“RSA/ECB/PKCS1Padding”):
- 优点:使用PKCS1填充模式,能够有效地防止一些攻击,如RSA公钥加密填充攻击。
- 缺点:加密后的密文长度为固定值,可能会导致一些问题,如数据过长时需要分块加密。
- 3.RSA_ECB(“RSA/ECB/NoPadding”):
- 优点:不使用填充模式,密文长度与明文长度相同,适合加密数据长度固定的场景。
- 缺点:容易受到一些攻击,如RSA公钥加密填充攻击,需要在实际使用中谨慎选择。
- 4.RSA_None(“RSA/None/NoPadding”):
- 优点:不使用填充模式,密文长度与明文长度相同,适合加密数据长度固定的场景。
- 缺点:容易受到一些攻击,如RSA公钥加密填充攻击,需要在实际使用中谨慎选择。
使用场景:主要用于公司产品的授权,通过传入加密后的授权码进行解密比对产品信息是否正确以及版本过期时间等
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import org.junit.jupiter.api.Test;
import org.springframework.util.FileCopyUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class LicenseTest {
@Test
public void test() throws IOException {
System.out.println("----start-----------");
InputStream publicKey = this.getClass().getClassLoader().getResourceAsStream("system/publicKey");
InputStream privateKey = this.getClass().getClassLoader().getResourceAsStream("system/privateKey");
String PUBLIC_KEY = new String(FileCopyUtils.copyToByteArray(publicKey));
String PRIVATE_KEY = new String(FileCopyUtils.copyToByteArray(privateKey));
//此处直接用hutool工具包中的加解密工具,如果一直加密内容和公钥则私钥可为null
RSA rsa = new RSA(AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue(), PRIVATE_KEY, PUBLIC_KEY);
//公钥加密,私钥解密
byte[] encrypt = rsa.encrypt(StrUtil.bytes("需要加密的内容,我主要适用于对授权码进行解密验证产品是否授权,是否在有效期内", StandardCharsets.UTF_8), KeyType.PrivateKey);
System.out.println("encrypt:" + Base64.getEncoder().encodeToString(encrypt));
byte[] decrypt1 = rsa.decrypt(encrypt, KeyType.PublicKey);
String decryptedString = new String(decrypt1, StandardCharsets.UTF_8);
System.out.println("decryptedString:" + decryptedString);
System.out.println("----end-----------");
}
}