一般金融類的產品,涉及前端和后端交互的時候,都會都嚴格的數據安全保證。防止黑客攻擊,信息篡改。
加密方式有很多,總的來說,分為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