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填充模式时,即使每次的数据和秘钥相同,产生的密文也会不同,从而提高数据的安全性。