对称加密+非对称加密,实现数据安全传输
一般金融類的產品,涉及前端和后端交互的時候,都會都嚴格的數據安全保證。防止黑客攻擊,信息篡改。
加密方式有很多,總的來說,分為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);//生成大小 1024KeyPair 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");//指定RSAprivateKey = 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();}?
??????????????????????????????????????????????????????????????????????????????? 掃碼關注,共同進步
?
?
總結
以上是生活随笔為你收集整理的对称加密+非对称加密,实现数据安全传输的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蓝牙协议栈消息的关联
- 下一篇: IPGUARD苹果系统客户端安装与卸载