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