一.什么是安全传输?
安全传输是,即使人们从网络上听到我们发送的数据包,他们也无法破译我们的信息,或者破译的机会非常渺茫。 那么这是如何实现的呢? 毕竟,如果我们想传输加密信息,接收者需要密钥解密,密钥也需要通过网络传输!
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/span> 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));
}
}