目录
随着计算机网络的发展,网络中的安全问题也日趋严重。
HTTPS
HTTPS (全称:Hypertext Transfer Protocol Secure ),是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性 。HTTPS 在HTTP 的基础下加入SSL,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。
SSL
安全套接层SSL由Netscape于1994年开发,广泛应用于基于万维网的各种网络应用(但不限于万维网应用)。
SSL作用在端系统应用层的HHTP和运输层之间,在TCP之上建立起一个安全通道,为通过TCP传输的应用层提供安全保障。
在发送方,SSL 接收应用层的数据,对数据进行加密,然后把加了密的数据送往 TCP 套接字。在接收方,SSL 从 TCP 套接字读取数据,解密后把数据交给应用层。
加密的方式
1.对称密钥加密
对称密钥加密,即加密密钥与解密密钥是相同的密码体制。
使用Java实现AES对称加密:(AES加密了解)
package demo;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AesKit {
//加密
public static String encry(String content ,String key) {
String result = "";
try {
//将原始加密内容转换为字节数组
byte[] source = content.getBytes();
//创建AES加密算法对象
//设置填充方式为PKCS5Padding
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
//创建密钥
SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES");
//初始化
//参数1:操作模式,Cipher.ENCRYPT_MODE代表加密操作,Cipher.DECRYPT_MODE代表解密
//参数2:密钥
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
//执行最终操作(加密)
byte[] resultByteArray = cipher.doFinal(source);
//将加密结果(字节数组)使用Base64编码成字符串内容
result = Base64.getEncoder().encodeToString(resultByteArray);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return result;
}
//解密
public static String decry(String content ,String key) {
byte[] source = Base64.getDecoder().decode(content);
String result = "";
try {
//创建AES加密算法对象
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
//创建密钥
SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES");
//初始化
//参数1:操作模式,Cipher.ENCRYPT_MODE代表加密操作,Cipher.DECRYPT_MODE代表解密
//参数2:密钥
cipher.init(Cipher.DECRYPT_MODE, secretKey);
//执行最终操作(解密)
byte[] resultByteArray = cipher.doFinal(source);
//将解密结果(字节数组)转成字符串内容
result = new String(resultByteArray);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return result;
}
}
测试类
package demo
public class test {
public static void main(String[] args) {
String str="hello";
String key="1234567890abcdef";
System.out.println("原始内容");
//先加密
String encryResult = AesKit.encry(str, key);
System.out.println("AES加密结果(ECB工作模式):"+encryResult);
//再解密
String decryResult = AesKit.decry(encryResult, key);
System.out.println("AES解密结果(ECB工作模式):"+decryResult);
}
}
输出结果:
2.非对称密钥加密
非对称密钥加密,使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。
在公钥密码体制中,加密密钥(即公钥) PK 是公开信息,而解密密钥(即私钥或秘钥) SK 是需要保密的。
加密算法 E 和解密算法 D 也都是公开的。
虽然秘钥 SK 是由公钥 PK 决定的,但却不能根据 PK 计算出 SK。
使用Java实现非对称式加密(RSA):
package demo;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class RsaKit {
//私钥
PrivateKey sk;
//公钥
PublicKey pk;
//构造方法
public RsaKit() throws GeneralSecurityException {
//创建密钥生成器
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
kpGen.initialize(1024);//设置长度
//生成"密钥对"
KeyPair kp = kpGen.generateKeyPair();
//通过"密钥对",分别获取公钥和私钥
this.sk = kp.getPrivate();
this.pk = kp.getPublic();
}
//把私钥导出为字节
public byte[] getPrivateKey() {
return this.sk.getEncoded();
}
//把公钥导出为字节
public byte[] getPublicKey() {
return this.pk.getEncoded();
}
//用公钥加密
public byte[] encrypt(byte[] message) throws GeneralSecurityException {
//创建RSA加密算法对象
Cipher cipher = Cipher.getInstance("RSA");
//初始化
//参数1:操作模式,Cipher.ENCRYPT_MODE代表加密操作,Cipher.DECRYPT_MODE代表解密
//参数2:公钥
cipher.init(Cipher.ENCRYPT_MODE, this.pk);
//执行最终操作(加密)
byte[] resultByteArray = cipher.doFinal(message);
return resultByteArray;
}
//用私钥解密
public byte[] decrypt(byte[] input) throws GeneralSecurityException {
//创建RSA加密算法对象
Cipher cipher = Cipher.getInstance("RSA");
//初始化
//参数1:操作模式,Cipher.ENCRYPT_MODE代表加密操作,Cipher.DECRYPT_MODE代表解密
//参数2:私钥
cipher.init(Cipher.DECRYPT_MODE, this.sk);
//执行最终操作(解密)
return cipher.doFinal(input);
}
}
注意加密和解密所使用的密钥
测试类:
package demo;
import java.math.BigInteger;
public class TestRsa {
public static void main(String[] args) {
String str="hello";
try {
//RSA加密
//创建自定义的RSA加密对象
RsaKit rsa = new RsaKit();
//获取公钥
byte[] pk = rsa.getPublicKey();
System.out.println(String.format("public Key(公钥):%x", new BigInteger(1,pk)));
//使用公钥进行加密
byte[] encryptResultArray = rsa.encrypt(str.getBytes());
System.out.println(String.format("使用公钥加密后的结果:%x",new BigInteger(1,encryptResultArray)));
//获取私钥
byte[] sk = rsa.getPublicKey();
System.out.println(String.format("private Key(私钥):%x",new BigInteger(1,sk)));
//使用私钥解密
byte[] decryptResultArray = rsa.decrypt(encryptResultArray);
System.out.printf("使用私钥解密后的结果:"+new String(decryptResultArray));
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
输出结果:
HTTPS工作流程
1.用户通过浏览器请求https网站,服务器收到请求,选择浏览器与服务器协商的加密算法,并将数字证书返回给浏览器。
2.浏览器对收到的数字证书进行验证(用CA发布的公钥鉴别数字证书),如果存在问题,则会发生一个提示。如果验证通过则会生成一个密钥X,并且使用公钥进行加密,发送给服务器。
3.服务器收到之后,使用私钥进行解密,得到浏览器生成的密钥X,然后使用密钥X对所要发送给浏览器的信息进行加密,随后发送。
4.浏览器收到来自服务器的信息,使用之前生成的密钥X进行解密,得到最终网页中所需要的内容。
大致的图解: