对称加密+非对称加密,实现数据安全传输
一般金融类的产品,涉及前端和后端交互的时候,都会都严格的数据安全保证。防止黑客攻击,信息篡改。
加密方式有很多,总的来说,分为2种:对称和非对称。我们先来看一下,这两种加密方式分别是什么?他们有什么区别?
对称加密:
对称加密,即采用对称的密码编码技术,他的特点是,加密和解密使用相同的秘钥。
常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES。对称加密算法使用起来简单快捷,密钥较短,且破译困难。
但是对称秘钥在使用过程中存在以下问题:
1、对称加密算法一般不能提供信息完整性的鉴别。它无法验证发送者和接受者的身份;
2、对称密钥的管理和分发工作是一件具有潜在危险的和烦琐的过程。如何防止秘钥泄露是一个难点。
非对称加密:
非对称加密技术,需要两个秘钥,公钥和私钥。公钥和私钥成对出现。
如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。
非对称加密的典型应用是数字签名。
常见的非对称加密算法有:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)。
对称+非对称结合使用:
现在,我们已经对对称和非对称加密有了一定的了解。接下来,我将会给大家介绍一下,我在项目中使用的一种加密方式:对称+非对称。
先看一张流程图:
先看发送方:
这里,我们主要有2步操作。
1、报文原文使用对称加密技术。对称加密的秘钥(避免混淆,这里称对称密码)。根据随机数生成。每次发起请求时,会重新产生一个随机数,进一步降低被破解的风险。
2、对称密码通过非对称加密方式进行加密。公钥由后台产生,匹配的私钥由后台保管。这样产生一个加密后的对称密码。前端在发送给后端之后,后端需要用匹配的私钥才能解开。
再看接收方:
接收方在接收到数据包之后,同样有两步操作:
1、会使用匹配的私钥解密加密的对称密码,获取到真实的对称密码。
2、使用对称密码,解密加密报文,获取原报文内容。
这样做的好处是:
1、因为我们的对称密码是使用非对称加密的,因此,想要破解,需要找到相应的公钥才行。
2、每次请求会重新生成一个对称密码,这就加大了破解的难度。
代码实现:
工具类:
非对称加密:
public class RSA1 {
/**
* 随机生成公钥和私钥
*/
public static final String publicKeyString = "publicKeyString";
public static final String privateKeyString = "privateKeyString";
public static HashMap<String, String> getRandomKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);//生成大小 1024
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();//获取公钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();//获取私钥
HashMap<String, String> keyMap = new HashMap<String, String>();
keyMap.put(publicKeyString, new String(Base64.encode(publicKey.getEncoded(), Base64.DEFAULT)));//获取公钥Base64编码
keyMap.put(privateKeyString, new String(Base64.encode(privateKey.getEncoded(), Base64.DEFAULT)));//获取密钥Base64编码
return keyMap;
}
/**
* 通过字符串生成私钥
*/
public static PrivateKey getPrivateKey(String privateKeyData) {
PrivateKey privateKey = null;
try {
byte[] decodeKey = Base64.decode(privateKeyData, Base64.DEFAULT); //将字符串Base64解码
PKCS8EncodedKeySpec x509 = new PKCS8EncodedKeySpec(decodeKey);//创建x509证书封装类
KeyFactory keyFactory = KeyFactory.getInstance("RSA");//指定RSA
privateKey = keyFactory.generatePrivate(x509);//生成私钥
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return privateKey;
}
/**
* 通过字符串生成公钥
*/
public static PublicKey getPublicKey(String publicKeyData) {
PublicKey publicKey = null;
try {
byte[] decodeKey = Base64.decode(publicKeyData, Base64.DEFAULT);
X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodeKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(x509);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return publicKey;
}
/**
* 加密
*/
public static byte[] encrypt(String data, Key key) {
try {
//取公钥
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm(),"BC");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(data.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解密
*/
public static byte[] decrypt(byte[] data, Key key) {
try {
Cipher cipher = Cipher.getInstance("RSA","BC");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
对称加密:
public class AES_2 {
public static byte[] genPrivateKey(String password) throws NoSuchAlgorithmException {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
byte[] bytes = tohash256Deal(password);
SecureRandom securerandom = new SecureRandom(bytes);
kgen.init(128, securerandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
return key.getEncoded();
}
public static byte[] encrypt(String content, SecretKeySpec key) {
try {
//创建一个实现指定转换的 Cipher对象,该转换由指定的提供程序提供。
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteContent = content.getBytes("utf-8");
byte[] cryptograph = cipher.doFinal(byteContent);
return Base64.encode(cryptograph, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decrypt(byte[] cryptograph, SecretKeySpec key) {
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] content = cipher.doFinal(Base64.decode(cryptograph, Base64.DEFAULT));
return new String(content);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] encrypt(String content, String password) {
try {
//"AES":请求的密钥算法的标准名称
KeyGenerator kgen = KeyGenerator.getInstance("AES");
//256:密钥生成参数;securerandom:密钥生成器的随机源
SecureRandom securerandom = new SecureRandom(tohash256Deal(password));
kgen.init(128, securerandom);
//生成秘密(对称)密钥
SecretKey secretKey = kgen.generateKey();
//返回基本编码格式的密钥
byte[] enCodeFormat = secretKey.getEncoded();
//根据给定的字节数组构造一个密钥。enCodeFormat:密钥内容;"AES":与给定的密钥内容相关联的密钥算法的名称
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
//将提供程序添加到下一个可用位置
Security.addProvider(new BouncyCastleProvider());
//创建一个实现指定转换的 Cipher对象,该转换由指定的提供程序提供。
//"AES/ECB/PKCS7Padding":转换的名称;"BC":提供程序的名称
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteContent = content.getBytes("utf-8");
byte[] cryptograph = cipher.doFinal(byteContent);
return Base64.encode(cryptograph, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decrypt(byte[] cryptograph, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom securerandom = new SecureRandom(tohash256Deal(password));
kgen.init(128, securerandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] content = cipher.doFinal(Base64.decode(cryptograph, Base64.DEFAULT));
return new String(content);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
public static byte[] tohash256Deal(String datastr) {
try {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(datastr.getBytes());
byte[] hex = digester.digest();
return hex;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e.getMessage());
}
}
}
发送方和接收方的实现:
String content = "000";
JSONObject jsonObject = new JSONObject();
try {
LogT.i("++++++++++++++++++++++发送方+++++++++++++++++++++++++=");
//产生私钥
int random = (int) ((Math.random() * 9 + 1) * 100000);
//私钥字节
byte[] bytes = AES_2.genPrivateKey(String.valueOf(random));
//传输报文加密
SecretKeySpec key1 = new SecretKeySpec(bytes, "AES");
byte[] content_encrypt = AES_2.encrypt(content, key1);
//公钥对私钥加密
PublicKey publicKey = RSA1.getPublicKey(public_key);
sKey_encrypt = RSA1.encrypt(Base64.encodeToString(bytes, Base64.DEFAULT), publicKey);
//数据组装
jsonObject.put("key", Base64.encodeToString(sKey_encrypt, Base64.DEFAULT));
jsonObject.put("content", AES_2.parseByte2HexStr(content_encrypt));
LogT.i("+++++++++++++++++++++++接收方++++++++++++++++++++++++=");
//解析获取私钥
PrivateKey privateKey = RSA1.getPrivateKey(private_key);
//解析接收到的key数据
byte[] decode = Base64.decode(Base64.encodeToString(sKey_encrypt, Base64.DEFAULT), Base64.DEFAULT);
//私钥解密
byte[] decrypt = RSA1.decrypt(decode, privateKey);
//解码私钥字节
byte[] decode_orig = Base64.decode(new String(decrypt), Base64.DEFAULT);
//加密的报文
byte[] HexStrByte = AES_2.parseHexStr2Byte(AES_2.parseByte2HexStr(content_encrypt));
SecretKeySpec key2 = new SecretKeySpec(decode_orig, "AES");
//解密后的报文
String decrypt1 = AES_2.decrypt(HexStrByte, key2);
LogT.i(decrypt1);//000
} catch (Exception e) {
e.printStackTrace();
}
参考:
原文:https://blog.csdn.net/Aminy123/article/details/81871092