简介
RSA是一种公钥密码算法,它的名字是由它的三位开发者,即Ron Rivest、Adi Shamir 和 Leonard Adleman 的姓氏的首字母组成的。RSA可以被用于公钥密码和数字签名。RSA是被研究得最广泛的公钥算法,从提出到现在已近三十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。1983年麻省理工学院在美国为RSA算法申请了专利。
安全性
RSA的安全性依赖于大数分解。换句话说,RSA的难度与大数分解难度等价,一旦发现了对大整数进行质因数分解的高效算法,RSA就能够被破译。这点将在下述对 N 的讨论着重体现。
概述
在计算机中常用的加密算法分为两类:对称加密算法和非对称加密算法。
1.对称加密
在对称加密技术中,对信息的加密和解密都使用了相同的密钥Key,也就是说使用同一个密钥Key对数据进行加密和解密。这种加密方法可简化加解密的处理过程,信息交换双方都不必彼此研究和交换专用的加解米算法。如果在交换阶段,密钥Key没有泄露,那么加密数据的机密性和报文的完整性就可以得到保证。
2.非对称加密
在非对称加密中,不再只有一个密钥Key了。在非对称加密算法中,密钥被分解为一对,一个称为公开密钥,另一个称为私有密钥。对于公钥,可以通过非保密方式向他人公开,而私钥则由解密方保密,不对别人公开。
3.非对称加密的应用
由于非对称加密方式可以使通信双方无需事先交换密钥就可以建立安全通信,因此被广泛应用于身份认证、数字签名、等信息交换领域。其中最具有代表性的非对称加密方式就是RSA公钥密码体制。
流程介绍
图示
1.生成公共参数GC
import java.math.BigInteger;
import java.security.SecureRandom;
public class PublicParametersGenerator {
public String generateParameters(int k) {
// 使用安全参数k生成公共参数cp
BigInteger p = generatePrime(k); // 生成大素数p
BigInteger q = generatePrime(k); // 生成大素数q
BigInteger n = p.multiply(q); // 计算n = p * q
// 转换为16进制表示,并在开头添加0x以表示十六进制数
String hexString = n.toString(16);
return hexString;
}
private BigInteger generatePrime(int bitLength) {
// 使用特定的算法生成长度略大于2048位的大素数
SecureRandom random = new SecureRandom();
BigInteger prime = BigInteger.probablePrime(bitLength, random); // 略大于2048位
return prime.subtract(BigInteger.ONE).shiftRight(1).multiply(BigInteger.TWO).add(BigInteger.ONE);
}
public static void main(String[] args) {
PublicParametersGenerator generator = new PublicParametersGenerator();
int securityParameter = 2048; // 安全参数,例如2048位长度
String publicParameters = generator.generateParameters(securityParameter);
System.out.println("生成的公共参数为:" + publicParameters);
System.out.println("公共参数长度为:" + publicParameters.length());
}
}
2.生成签名者密钥GKS
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class KeyGeneration {
public static KeyPair generateKeyPair(String cp) throws NoSuchAlgorithmException {
// 解析公共参数
int keySize = cp.length();// 密钥长度,假设以字符串形式传入
SecureRandom secureRandom = new SecureRandom(); // 使用安全的随机数生成器
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(keySize, secureRandom);
return keyGen.generateKeyPair();
}
public static void main(String[] args) {
try {
PublicParametersGenerator parametersGenerator = new PublicParametersGenerator();
String cp = parametersGenerator.generateParameters(2048); // 假设生成256位的公共参数cp
KeyGeneration keyGeneration = new KeyGeneration();
KeyPair keyPair = keyGeneration.generateKeyPair(cp);
System.out.println("签名者的私钥: " + keyPair.getPrivate());
System.out.println("签名者的公钥: " + keyPair.getPublic());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
3.生成验证者密钥GKV
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class VerifierKeyGeneration {
// 生成验证者密钥对(sk3, pk3)的方法
public KeyPair generateKeyPair(String cp) throws NoSuchAlgorithmException {
int keySize = cp.length();// 密钥长度,假设以字符串形式传入
SecureRandom secureRandom = new SecureRandom(); // 使用安全的随机数生成器
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(keySize, secureRandom);
return keyGen.generateKeyPair();
}
public static void main(String[] args) {
try {
PublicParametersGenerator parametersGenerator = new PublicParametersGenerator();
String cp = parametersGenerator.generateParameters(2048); // 假设生成256位的公共参数cp
KeyGeneration keyGeneration = new KeyGeneration();
KeyPair signerKeyPair = keyGeneration.generateKeyPair(cp); // 生成签名者密钥对(sk1, pk1)
VerifierKeyGeneration verifierKeyGeneration = new VerifierKeyGeneration();
KeyPair verifierKeyPair = verifierKeyGeneration.generateKeyPair(cp); // 生成验证者密钥对(sk3, pk3)
System.out.println("签名者的私钥: " + signerKeyPair.getPrivate());
System.out.println("签名者的公钥: " + signerKeyPair.getPublic());
System.out.println("验证者的私钥: " + verifierKeyPair.getPrivate());
System.out.println("验证者的公钥: " + verifierKeyPair.getPublic());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
4.签名S
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
public class SignatureGeneration {
// 生成签名者的公开可验证(PV)签名σ的方法
public String generateSignature(String sk1, String message) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, InvalidKeySpecException {
byte[] privateKeyBytes = Base64.getDecoder().decode(sk1);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(message.getBytes());
byte[] signatureBytes = signature.sign();
return Base64.getEncoder().encodeToString(signatureBytes);
}
public static void main(String[] args) {
try {
PublicParametersGenerator parametersGenerator = new PublicParametersGenerator();
String cp = parametersGenerator.generateParameters(2048); // 假设生成256位的公共参数cp
KeyGeneration keyGeneration = new KeyGeneration();
KeyPair signerKeyPair = keyGeneration.generateKeyPair(cp); // 生成签名者密钥对(sk1, pk1)
String sk1 = Base64.getEncoder().encodeToString(signerKeyPair.getPrivate().getEncoded());
String message = "Hello, world!";
SignatureGeneration signatureGeneration = new SignatureGeneration();
String signature = signatureGeneration.generateSignature(sk1, message); // 生成签名者的PV签名σ
System.out.println("签名者的PV签名σ: " + signature);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
}
}
5.公开验证V
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class Verification {
// 公开验证签名有效性的方法
public boolean verifySignature(String pk1, String message, String signature) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
byte[] publicKeyBytes = Base64.getDecoder().decode(pk1);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
Signature verifier = Signature.getInstance("SHA256withRSA");
verifier.initVerify(publicKey);
verifier.update(message.getBytes());
byte[] signatureBytes = Base64.getDecoder().decode(signature);
return verifier.verify(signatureBytes);
}
public static void main(String[] args) {
try {
PublicParametersGenerator parametersGenerator = new PublicParametersGenerator();
String cp = parametersGenerator.generateParameters(2048); // 假设生成256位的公共参数cp
KeyGeneration keyGeneration = new KeyGeneration();
KeyPair signerKeyPair = keyGeneration.generateKeyPair(cp); // 生成签名者密钥对(sk1, pk1)
String pk1 = Base64.getEncoder().encodeToString(signerKeyPair.getPublic().getEncoded());
String message = "Hello, world!";
SignatureGeneration signatureGeneration = new SignatureGeneration();
String signature = signatureGeneration.generateSignature(Base64.getEncoder().encodeToString(signerKeyPair.getPrivate().getEncoded()), message); // 生成签名者的PV签名σ
Verification verification = new Verification();
boolean isValid = verification.verifySignature(pk1, message, signature); // 公开验证签名有效性
if (isValid) {
System.out.println("签名有效");
} else {
System.out.println("签名无效");
}
} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
}
}
测试
添加简单的前端后,用以上逻辑来模拟Alice,Bob之间的信息传递与防泄漏