import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import javax.crypto.Cipher;
public class RSAExample {
public static void main(String[] args) throws Exception {
try {
// 生成RSA密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
System.out.println("priveteKey:" + Base64.getEncoder().encode(privateKey.getEncoded()));
System.out.println("publicKey:" + Base64.getEncoder().encode(publicKey.getEncoded()));
// 加密明文
String plaintext = "KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(\"RSA\");";
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT\_MODE, publicKey);
byte[] ciphertext = encryptCipher.doFinal(plaintext.getBytes());
// 解密密文
Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT\_MODE, privateKey);
byte[] plaintextBytes = decryptCipher.doFinal(ciphertext);
String decryptedText = new String(plaintextBytes);
System.out.println("plaintext: " + plaintext);
System.out.println("encryptCipher: " + ciphertext.length + " size");
System.out.println("encryptCipherText: " + new String(ciphertext, StandardCharsets.UTF\_8));
System.out.println("decryptCipherText: " + decryptedText);
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出结果:
这段代码首先生成一个RSA密钥对,然后使用公钥加密一个明文字符串,最后使用私钥解密它。这个简单的例子展示了RSA的基本工作原理。然而,在实际应用中,还需要考虑其他安全性因素,如密钥管理、安全协议等。
4、实现RSA算法
RSA是一种非对称加密算法,它使用一对密钥,其中一个公开用于加密,另一个保密用于解密。下面是RSA算法的计算过程:
- 选择两个大质数p和q,并计算它们的积n=p*q。
- 选择一个公开的指数e,要求e和φ(n)=(p-1)*(q-1)(欧拉函数)互质,即gcd(e, φ(n))=1。
- 计算与e互质的模反元素d,即gcd(d, φ(n))=1且d*e≡1 mod φ(n)。
- 将p和q销毁,使得只有授权的实体能够重新获得它们。
加密过程:
- 对于要加密的明文消息m,将其转化为一个整数小于n。
- 对m进行加密,得到密文c,计算公式为c=m^e mod n。
- 将密文c发送给接收者。
解密过程:
- 接收者收到密文c后,使用自己的私钥d对c进行解密,得到明文m,计算公式为m=c^d mod n。
由于d和φ(n)互质,根据费马小定理,有c^d mod n=(me)d mod n=(m^(ed)) mod n=m^(ed*mod n) mod n=m。
package com.example.demo;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
public class DemoMain {
public static void main(String[] args) throws UnsupportedEncodingException {
// 选择两个质数p和q
BigInteger p = new BigInteger("11");
BigInteger q = new BigInteger("19");
// 计算n和φ(n)
BigInteger n = p.multiply(q);
BigInteger phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
System.out.println("n:" + n);
System.out.println("phi:" + phi);
// 选择一个公开的指数e,并计算模反元素d
BigInteger e = new BigInteger("7");
BigInteger d = e.modInverse(phi);
// 公钥和私钥
BigInteger publicKey = e;
BigInteger privateKey = d;
System.out.println("公钥:" + publicKey);
System.out.println("私钥:" + privateKey);
// 明文消息
String plaintext = "kexuexiong";
//一、私钥加密,公钥解密,模拟服务器发消息给客户端
System.out.println("-------------------------------------私钥加密,公钥解密,模拟服务器发消息给客户端---------------------------------");
processing(n, e, d, plaintext);
//二、公钥加密,私钥解密,模拟客户端发消息给服务器
System.out.println("-------------------------------------公钥加密,私钥解密,模拟客户端发消息给服务器---------------------------------");
plaintext = "hello ,rose and jeck!!";
processing(n, d, e, plaintext);
}
private static void processing(BigInteger n, BigInteger e, BigInteger d, String plaintext) throws UnsupportedEncodingException {
System.out.println("需要加密的明文:"+plaintext);
// 加密过程
byte[] bytes = plaintext.getBytes("utf-8");
List<String> plaintextList = new LinkedList<>();
for (Byte aByte : bytes) {
BigInteger message = new BigInteger(aByte.toString());
BigInteger ciphertext = message.modPow(d, n);//加密之后的值可能超过Byte的最大值,所以直接用string保存
plaintextList.add(ciphertext.toString());
}
System.out.println("加密后队列:"+plaintextList);
// 解密过程
List<Byte> cipherList = new LinkedList<>();
for (String ciphertext : plaintextList) {
BigInteger decryptedMessage = new BigInteger(ciphertext).modPow(e, n);
cipherList.add(decryptedMessage.byteValue());
}
System.out.println("解密后队列信息: " + cipherList);
byte[] bytesMsg = new byte[cipherList.size()];
for (int i = 0; i < cipherList.size(); i++) {
bytesMsg[i] = cipherList.get(i);
}
System.out.println("解密后信息:" + new String(bytesMsg, "utf-8"));
}
}
输出结果:
n:209
phi:180
公钥:7
私钥:103
-------------------------------------私钥加密,公钥解密,模拟服务器发消息给客户端---------------------------------
需要加密的明文:kexuexiong
加密后队列:[50, 118, 175, 90, 118, 175, 51, 100, 143, 141]
解密后队列信息: [107, 101, 120, 117, 101, 120, 105, 111, 110, 103]
解密后信息:kexuexiong
-------------------------------------公钥加密,私钥解密,模拟客户端发消息给服务器---------------------------------
需要加密的明文:hello ,rose and jeck!!
加密后队列:[80, 161, 48, 48, 188, 10, 66, 38, 188, 58, 161, 10, 147, 165, 111, 10, 182, 161, 44, 145, 22, 22]
解密后队列信息: [104, 101, 108, 108, 111, 32, 44, 114, 111, 115, 101, 32, 97, 110, 100, 32, 106, 101, 99, 107, 33, 33]
解密后信息:hello ,rose and jeck!!
Process finished with exit code 0
4、Java中的源码对比解读
JavaScript
-
js的基本类型有哪些?引用类型有哪些?null和undefined的区别。
-
如何判断一个变量是Array类型?如何判断一个变量是Number类型?(都不止一种)
-
Object是引用类型嘛?引用类型和基本类型有什么区别?哪个是存在堆哪一个是存在栈上面的?
-
JS常见的dom操作api
-
解释一下事件冒泡和事件捕获
-
事件委托(手写例子),事件冒泡和捕获,如何阻止冒泡?如何组织默认事件?
-
对闭包的理解?什么时候构成闭包?闭包的实现方法?闭包的优缺点?
-
this有哪些使用场景?跟C,Java中的this有什么区别?如何改变this的值?
-
call,apply,bind
-
显示原型和隐式原型,手绘原型链,原型链是什么?为什么要有原型链
-
创建对象的多种方式
-
实现继承的多种方式和优缺点
-
new 一个对象具体做了什么
-
手写Ajax,XMLHttpRequest
-
变量提升
-
举例说明一个匿名函数的典型用例
-
指出JS的宿主对象和原生对象的区别,为什么扩展JS内置对象不是好的做法?有哪些内置对象和内置函数?
-
attribute和property的区别
-
document load和document DOMContentLoaded两个事件的区别
-
JS代码调试