DES加密:
DES 使用一個 56 位的密鑰以及附加的 8 位奇偶校驗位(每組的第8位作爲奇偶校驗位),產生最大 64 位的分組大小。這是一個迭代的分組密碼,使用稱爲 Feistel 的技術,其中將加密的文本塊分成兩半。使用子密鑰對其中一半應用循環功能,然後將輸出與另一半進行“異或”運算;接着交換這兩半,這一過程會繼續下去,但最後一個循環不交換。DES 使用 16 輪循環,使用異或,置換,代換,移位操作四種基本運算。
Android中的使用還是比較簡單的,java庫中已經封裝好了相應的接口,只需要按照規則進行調用即可。
private static String Algorithm = "DES";
private static String privKey = "";
/** * 加密 * * @param input * @param key * @return * @throws Exception */ public static byte[] encryptData(byte[] input, byte[] key) throws Exception { SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(Algorithm); DESKeySpec keySpec = new DESKeySpec(key); Key deskey = keyFactory.generateSecret(keySpec); Cipher c1 = Cipher.getInstance(Algorithm); c1.init(Cipher.ENCRYPT_MODE, deskey); byte[] cipherByte = c1.doFinal(input); return cipherByte; }
/** * 解密 * * @param input * @param key * @return * @throws Exception */ public static byte[] decryptData(byte[] input, byte[] key) throws Exception { SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(Algorithm); DESKeySpec keySpec = new DESKeySpec(key); Key deskey = keyFactory.generateSecret(keySpec); Cipher c1 = Cipher.getInstance(Algorithm); c1.init(Cipher.DECRYPT_MODE, deskey); byte[] clearByte = c1.doFinal(input); return clearByte; }
/** * 默認key * * @return */ public static byte[] getDefaultKey() { return privKey.getBytes(); }
AES加密:
高級加密標準(英語:Advanced
Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣爲全世界所使用。
Android中的使用和DES的方法類似,只是在key的生成方式中有些不同。
private static String Algorithm = "AES"; private static String privKey = "";
private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance(Algorithm); SecureRandom sr = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { sr = SecureRandom.getInstance("SHA1PRNG", "Crypto"); } else { sr = SecureRandom.getInstance("SHA1PRNG"); } sr.setSeed(seed); kgen.init(256, sr); // 192 and 256 bits may not be available SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } public static byte[] encrypt(byte[] input) throws Exception { try { byte[] raw = getRawKey(privKey.getBytes()); SecretKeySpec skeySpec = new SecretKeySpec(raw, Algorithm); Cipher cipher = Cipher.getInstance(Algorithm); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); byte[] encrypted = cipher.doFinal(input); return encrypted; } catch (Exception e) { e.printStackTrace(); return input; } } public static byte[] decrypt(byte[] encrypted) throws Exception { try { byte[] raw = getRawKey(privKey.getBytes()); SecretKeySpec skeySpec = new SecretKeySpec(raw, Algorithm); Cipher cipher = Cipher.getInstance(Algorithm); cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; } catch (Exception e) { e.printStackTrace(); return encrypted; } }
RSA加密:
RSA公鑰加密算法是1977年由羅納德·李維斯特(Ron
Rivest)、阿迪·薩莫爾(Adi
Shamir)和倫納德·阿德曼(Leonard
Adleman)一起提出的。1987年首次公佈,當時他們三人都在麻省理工學院工作。RSA就是他們三人姓氏開頭字母拼在一起組成的。RSA是目前最有影響力的公鑰加密算法,它能夠抵抗到目前爲止已知的絕大多數密碼攻擊,已被ISO推薦爲公鑰數據加密標準。
RSA算法基於一個十分簡單的數論事實:將兩個大素數相乘十分容易,但是想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作爲加密密鑰。
Android中的實現方法和DES,AES比較相似。
private static final String PADDING = "RSA/None/PKCS1Padding"; private static final String ALGORITHM = "RSA"; private static final String PROVIDER = "BC"; private static final String ENCODDING = "UTF-8";
/** * 隨機生成RSA密鑰對 * * @param keyLength * 密鑰長度,範圍:512~2048 * 一般1024 * @return */ public static KeyPair generateRSAKeyPair(int keyLength) { try { KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM, PROVIDER); kpg.initialize(keyLength); return kpg.generateKeyPair(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } catch (NoSuchProviderException e) { e.printStackTrace(); return null; } } /** * 用公鑰加密 * 每次加密的字節數,不能超過密鑰的長度值減去11 * * @param data * 需加密數據的byte數據 * @param publicKey * 公鑰 * @return 加密後的byte型數據 */ public static byte[] encryptData(byte[] data, PublicKey publicKey) { try { Cipher cipher = Cipher.getInstance(PADDING, PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } catch (Exception e) { e.printStackTrace(); return data; } } /** * 用私鑰解密 * * @param encryptedData * 經過encryptedData()加密返回的byte數據 * @param privateKey * 私鑰 * @return */ public static byte[] decrpytData(byte[] encryptedData, PrivateKey privateKey) { try { Cipher cipher = Cipher.getInstance(PADDING, PROVIDER); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(encryptedData); } catch (Exception e) { e.printStackTrace(); return encryptedData; } }有一點需要注意,在Android中默認的RSA加密時無padding的,及直接使用Cipher.getInstance("RSA")不會進行額外的數據填充,從而加密的密文每次都是相同,而使用PKCS1Padding填充模式時,即使每次的數據和祕鑰相同,產生的密文也會不同,從而提高數據的安全性。