一.何为安全传输?
安全传输就是,即使人家从网络监听到我们发送的数据包,也无法破译我们的信息,或者破译的机会十分渺茫。
那么这是如何实现的呢? 毕竟,我们想要传输加密信息,接收者解密的话则需要密钥,而密钥也是需要通过网络传输的啊!!
1.非对称加密
密钥的安全传输需要用到一种特殊的加密技术: 非对称加密。
1.1 何为非对称加密?
一次非对称加密信息传输包含三个要素: 公钥,私钥,传输报文
- 公钥: 源服务器生成,通过网络传输到目标服务器
- 私钥: 源服务器生成,绝对保存在本地,不经过任何传输到任何地方,只存在源服务器本地。
- 传输报文: 通过公钥或私钥进行加解密
非对称加密运行流程如下:
首先,源服务器生成一对密钥: 公钥,私钥。 公钥通过网络明文发送给目标服务器,然后源服务器将要发送的报文用私钥加密后发送给目标服务器,目标服务器拿到密文用公钥解密(这个过程不安全,因为如果其他人监听到公钥了,那么他就可以用公钥对源服务器发出的报文进行解密) ,接着目标服务器用公钥对要发送的报文进行加密,发送到源服务器,源服务器用私钥进行解密即可(这个过程是安全的,因为私钥只有源服务器拥有)
1.2 非对称加密算法RSA实例
典型的非对称加密算法RSA应用实例:
package RSA;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
public class RSADemo {
private static final String ENCODE = "UTF-8";
private static final String AES = "AES";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
/**
* AES加密
* @param content 加密内容
* @param AES_IV 加密偏移量
* @param AES_KEY 加密密钥
* @return 密文
* @throws Exception 加密过程中出现的异常
*/
public static String AESEncryptEncode(String content,String AES_IV,String AES_KEY) throws Exception{
Base64.Decoder decoder = Base64.getDecoder();
byte[] keyByte = decoder.decode(AES_KEY);
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + 1;
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
SecretKeySpec secretKeySpec = new SecretKeySpec(keyByte,AES);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,new IvParameterSpec(decoder.decode(AES_IV)));
byte[] result = cipher.doFinal(content.getBytes(ENCODE));
return Base64.getEncoder().encodeToString(result);
}
/**
* AES解密
* @param content 密文
* @param AES_IV 解密偏移量
* @param AES_KEY 解密密钥
* @return 解密后明文
* @throws Exception 异常
*/
public static String AESDecodeDecrypt(String content,String AES_IV,String AES_KEY) throws Exception{
Base64.Decoder decoder = Base64.getDecoder();
byte[] keyByte = decoder.decode(AES_KEY);
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + 1;
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
SecretKeySpec secretKeySpec = new SecretKeySpec(keyByte,AES);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,new IvParameterSpec(decoder.decode(AES_IV)));
byte[] base64 = decoder.decode(content);
byte[] result = cipher.doFinal(base64);
return new String(result, Charset.forName(ENCODE));
}
/**
* Rsa生成公钥,密钥
* @return 返回公钥,密钥字符串数组 0--密钥 1--公钥
* @throws NoSuchAlgorithmException 异常信息
*/
public static String[] RsaGenera() throws NoSuchAlgorithmException {
// 1.初始化发送方密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
String[] results = new String[2];
results[0] = Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded());
results[1] = Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded());
return results;
}
/**
* Rsa私钥加密
* @param privateKey 私钥
* @param content 明文
* @return 返回密文
* @throws Exception 异常
*/
public static String RsaPrivateEncrypt(String privateKey,String content) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey1 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey1);
byte[] result = cipher.doFinal(content.getBytes(ENCODE));
//System.out.println("私钥加密、公钥解密 ---- 加密:" + Arrays.toString(result));
return Base64.getEncoder().encodeToString(result);
}
/**
* Rsa公钥解密
* @param publicKey 公钥
* @param content 密文
* @return 明文
* @throws Exception 异常
*/
public static String RsaPublicUnEncrypt(String publicKey,String content) throws Exception{
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey1);
byte[] result = cipher.doFinal(Base64.getDecoder().decode(content));
//System.out.println("私钥加密、公钥解密 ---- 解密:" + Base64.getEncoder().encodeToString(result));
return Base64.getEncoder().encodeToString(result);
}
/**
* Rsa公钥加密
* @param publicKey 公钥
* @param content 明文
* @return 密文
* @throws Exception 异常
*/
public static String RsaPublicEncrypt(String publicKey,String content) throws Exception{
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec2);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey1);
byte[] result = cipher.doFinal(content.getBytes(ENCODE));
//System.out.println("公钥加密、私钥解密 ---- 加密: "+Base64.getEncoder().encodeToString(result2));
return Base64.getEncoder().encodeToString(result);
}
/**
* Rsa私钥解密
* @param privateKey 私钥
* @param content 密文
* @return 解密后明文
* @throws Exception 异常
*/
public static String RsaPrivateUnEncrypt(String privateKey,String content) throws Exception{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey1 = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey1);
byte[] result = cipher.doFinal(Base64.getDecoder().decode(content));
//System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result));
return new String(result);
}
public static void main(String[] args) throws Exception {
String[] keys = RsaGenera();
System.out.println("RSA生成密钥对:");
System.out.println("公钥:"+keys[1]);
System.out.println("私钥:"+keys[0]);
String test = RsaPublicEncrypt(keys[1],"今天打老虎");
System.out.println("公钥加密:今天打老虎-->"+test);
String test2 = RsaPrivateUnEncrypt(keys[0],test);
System.out.println("私钥解密:"+test+"-->"+test2);
}
}
运行结果:
2.对称加密
对称加密技术是一种很广泛的加密技术。
2.1 何为对称加密
对称加密的元素主要有两个: 密钥,报文
- 密钥: 通信双方提前约定好的密钥
- 报文: 用相同的密钥进行加密和解密的报文
对称加密的运行流程如下:
首先通信双方约定好密钥,然后源服务器发送到目标服务器的密文用密钥加密,目标服务器用密钥解密密文即可。(如果密钥还是通过网络传输,则这种通信还是不安全的,除非双方线下约定且保证没有第三个人知道)
2.2 对称加密AES/CBC加密实例
package RSA;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Base64;
public class AESDemo {
private static final String ENCODE = "UTF-8";
private static final String AES = "AES";
private static final String AES_IV = "49U2GlzcrBmS9UVz+mEE3Q==";
private static final String AES_KEY = "D8M1+eb6mzq0Oc23K+YQYQ==";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
/**
* AES加密
* @param content 加密内容
* @param AES_IV 加密偏移量
* @param AES_KEY 加密密钥
* @return 密文
* @throws Exception 加密过程中出现的异常
*/
public static String AESEncryptEncode(String content,String AES_IV,String AES_KEY) throws Exception{
Base64.Decoder decoder = Base64.getDecoder();
byte[] keyByte = decoder.decode(AES_KEY);
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + 1;
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
SecretKeySpec secretKeySpec = new SecretKeySpec(keyByte,AES);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,new IvParameterSpec(decoder.decode(AES_IV)));
byte[] result = cipher.doFinal(content.getBytes(ENCODE));
return Base64.getEncoder().encodeToString(result);
}
/**
* AES解密
* @param content 密文
* @param AES_IV 解密偏移量
* @param AES_KEY 解密密钥
* @return 解密后明文
* @throws Exception 异常
*/
public static String AESDecodeDecrypt(String content,String AES_IV,String AES_KEY) throws Exception{
Base64.Decoder decoder = Base64.getDecoder();
byte[] keyByte = decoder.decode(AES_KEY);
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + 1;
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
SecretKeySpec secretKeySpec = new SecretKeySpec(keyByte,AES);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,new IvParameterSpec(decoder.decode(AES_IV)));
byte[] base64 = decoder.decode(content);
byte[] result = cipher.doFinal(base64);
return new String(result, Charset.forName(ENCODE));
}
public static void main(String[] args) throws Exception {
String m = AESEncryptEncode("今天打老虎",AES_IV,AES_KEY);
System.out.println("AES对称加密: "+m);
System.out.println("AES对称解密:"+AESDecodeDecrypt(m,AES_IV,AES_KEY));
}
}
运行结果:
3. 通过非对称+对称加密实现网络安全传输
通过前面的学习我们知道,安全传输的关键在于密钥不能被泄露,我们可以试想一下,我们能不能先用非对称加密传输密钥,然后用对称加密进行报文传输,这样的话不久实现了,加密传输。
流程如下:
首先源服务器生成私钥,公钥,将公钥发送给目标服务器,然后目标服务器用公钥加密对称密钥发送给源服务器,接着源服务器将密文解密得到对称密钥,这样就只有双方知道对称密钥了,不存在第三方知道了。
然后以后的信息传输就用对称密钥加解密即可。
3.1 结合RSA和AES/CBC实现安全传输Demo
非对称加密进行对称密钥传输,对称加密实现报文安全传输。
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
public class EncryptUtil {
private static final String ENCODE = "UTF-8";
private static final String AES = "AES";
private static final String AES_IV = "49U2GlzcrBmS9UVz+mEE3Q==";
private static final String AES_KEY = "D8M1+eb6mzq0Oc23K+YQYQ==";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
/**
* AES加密
* @param content 加密内容
* @param AES_IV 加密偏移量
* @param AES_KEY 加密密钥
* @return 密文
* @throws Exception 加密过程中出现的异常
*/
public static String AESEncryptEncode(String content,String AES_IV,String AES_KEY) throws Exception{
Base64.Decoder decoder = Base64.getDecoder();
byte[] keyByte = decoder.decode(AES_KEY);
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + 1;
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
SecretKeySpec secretKeySpec = new SecretKeySpec(keyByte,AES);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,new IvParameterSpec(decoder.decode(AES_IV)));
byte[] result = cipher.doFinal(content.getBytes(ENCODE));
return Base64.getEncoder().encodeToString(result);
}
/**
* AES解密
* @param content 密文
* @param AES_IV 解密偏移量
* @param AES_KEY 解密密钥
* @return 解密后明文
* @throws Exception 异常
*/
public static String AESDecodeDecrypt(String content,String AES_IV,String AES_KEY) throws Exception{
Base64.Decoder decoder = Base64.getDecoder();
byte[] keyByte = decoder.decode(AES_KEY);
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + 1;
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
SecretKeySpec secretKeySpec = new SecretKeySpec(keyByte,AES);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,new IvParameterSpec(decoder.decode(AES_IV)));
byte[] base64 = decoder.decode(content);
byte[] result = cipher.doFinal(base64);
return new String(result, Charset.forName(ENCODE));
}
/**
* Rsa生成公钥,密钥
* @return 返回公钥,密钥字符串数组 0--密钥 1--公钥
* @throws NoSuchAlgorithmException 异常信息
*/
public static String[] RsaGenera() throws NoSuchAlgorithmException {
// 1.初始化发送方密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
String[] results = new String[2];
results[0] = Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded());
results[1] = Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded());
return results;
}
/**
* Rsa私钥加密
* @param privateKey 私钥
* @param content 明文
* @return 返回密文
* @throws Exception 异常
*/
public static String RsaPrivateEncrypt(String privateKey,String content) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey1 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey1);
byte[] result = cipher.doFinal(content.getBytes(ENCODE));
//System.out.println("私钥加密、公钥解密 ---- 加密:" + Arrays.toString(result));
return Base64.getEncoder().encodeToString(result);
}
/**
* Rsa公钥解密
* @param publicKey 公钥
* @param content 密文
* @return 明文
* @throws Exception 异常
*/
public static String RsaPublicUnEncrypt(String publicKey,String content) throws Exception{
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey1);
byte[] result = cipher.doFinal(Base64.getDecoder().decode(content));
//System.out.println("私钥加密、公钥解密 ---- 解密:" + Base64.getEncoder().encodeToString(result));
return Base64.getEncoder().encodeToString(result);
}
/**
* Rsa公钥加密
* @param publicKey 公钥
* @param content 明文
* @return 密文
* @throws Exception 异常
*/
public static String RsaPublicEncrypt(String publicKey,String content) throws Exception{
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec2);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey1);
byte[] result = cipher.doFinal(content.getBytes(ENCODE));
//System.out.println("公钥加密、私钥解密 ---- 加密: "+Base64.getEncoder().encodeToString(result2));
return Base64.getEncoder().encodeToString(result);
}
/**
* Rsa私钥解密
* @param privateKey 私钥
* @param content 密文
* @return 解密后明文
* @throws Exception 异常
*/
public static String RsaPrivateUnEncrypt(String privateKey,String content) throws Exception{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey1 = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey1);
byte[] result = cipher.doFinal(Base64.getDecoder().decode(content));
//System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result));
return new String(result);
}
public static void main(String[] args) throws Exception {
String[] keys = RsaGenera();
String aes_key = RsaPublicEncrypt(keys[1],AES_KEY);
String aes_iv = RsaPublicEncrypt(keys[1],AES_IV);
String AES_KEY = RsaPrivateUnEncrypt(keys[0],aes_key);
String AES_IV = RsaPrivateUnEncrypt(keys[0],aes_iv);
String m = AESEncryptEncode("今天打老虎",AES_IV,AES_KEY);
System.out.println("AES对称加密: "+m);
System.out.println("AES对称解密:"+AESDecodeDecrypt(m,AES_IV,AES_KEY));
}
}