1、數字摘要
是指通過算法將長數據變為短數據,通常用來標識數據的唯一性,是否被修改,常用的加密算法有md5和sha1兩種,如Android的App簽名也是用的這兩種算法。
md5具有不可逆性,也可用來作為密碼加密,並且通常情況下為了讓加密過程變得不可預測,我們會進行加鹽操作,如下代碼:
/** * 使用md5方式進行加密 * @return */ public static String digest(String content){ StringBuilder builder = new StringBuilder(); try { MessageDigest msgDitest = MessageDigest.getInstance("MD5"); msgDitest.update(content.getBytes()); byte[] digests = msgDitest.digest(); //將每個字節轉為16進制 for (int i=0;i<digests.length;i++){ builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8為加鹽操作 } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return builder.toString(); }
sha1也具有不可逆性,比md5長度更長,所以更安全,但是機密的效率md5要慢一些,如文件的秒傳功能,以及相同的v4包沖突都是可以根據sha1值進行比對的。
/** * 使用sha-1方式進行加密 * @return */ public static String digest(String content){ StringBuilder builder = new StringBuilder(); try { MessageDigest msgDitest = MessageDigest.getInstance("SHA-1"); msgDitest.update(content.getBytes()); byte[] digests = msgDitest.digest(); //將每個字節轉為16進制 for (int i=0;i<digests.length;i++){ builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8為加鹽操作 } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return builder.toString(); }
不過呢,由於以上兩種生成數字摘要的算法都是不可逆的,對於可逆的加密算法中,按照密鑰的數量和加密規則一半分為對稱加密和非對稱加密兩類:
對稱加密:
密鑰可以自己指定,只有一把密鑰,如果密鑰泄漏數據就會暴漏;
常用的對稱加密算法有DES和AES兩種;
特點是加密速度快,但是缺點是安全性低,因為只要密鑰暴漏,數據就可以被解密。
非對稱加密的特點:
常見的非對稱加密算法是RSA;
他有兩把密鑰,且是由程序生成的,不能自己指定;
特點是加密速度比較慢,但是安全性比較高;
加密和解密的規則是:公鑰加密只能私鑰解密,私鑰加密只能公鑰解密;
應用場景舉例:在集成支付寶支付SDK時,需要生成私鑰和公鑰,公鑰需要設置到支付寶網站的管理后台,在程序中調用支付接口的時候,使用我們自己的私鑰進行加密,這樣支付寶在收到訂單信息之后就可以通過公鑰進行解密,其他人即時劫持了數據,但是沒有公鑰,也是無法解密的。
代碼實踐:使用AndroidUtils的工具類(工具類地址:https://github.com/zhaoyasong/ToolUtils)進行操作:
DES加密和解密的代碼如下:
String data = "我是俊哥"; String desKey = "青龍偃月刀";// 密鑰,口號 boolean isDesEncrypt = false; private void useDes() { try { if(isDesEncrypt){ //解密 text.setText(Des.decrypt(text.getText().toString(), desKey)); }else { //加密 text.setText(Des.encrypt(data, desKey)); } isDesEncrypt = !isDesEncrypt; } catch (Exception e) { e.printStackTrace(); } }
RSA加密和解密的代碼如下:
//1.生成密鑰對,設計口號 try { Map<String, Object> genKeyPair = RSACrypt.genKeyPair(); //2.獲取公鑰 publicKey = RSACrypt.getPublicKey(genKeyPair); //3.獲取私鑰 privateKey = RSACrypt.getPrivateKey(genKeyPair); } catch (Exception e) { e.printStackTrace(); } private boolean isRSAEncrypt = false; protected void useRSA() { try { if(isRSAEncrypt){ //公鑰解密 String str = text.getText().toString(); byte[] bs = RSACrypt.decryptByPublicKey(RSACrypt.decode(str), publicKey); text.setText(new String(bs)); }else { //私鑰加密 byte[] bs = RSACrypt.encryptByPrivateKey(data.getBytes(), privateKey); text.setText(RSACrypt.encode(bs)); } isRSAEncrypt = !isRSAEncrypt; } catch (Exception e) { e.printStackTrace(); } }