Android中AES的使用
AES是对称加密算法的一种,对称加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。
AES加密需要:明文 + 密钥+ 偏移量(IV)+密码模式(算法/模式/填充)
AES解密需要:密文 + 密钥+ 偏移量(IV)+密码模式(算法/模式/填充)
其中加密和解密的密钥,偏移量和密码模式要相同。实际工作中,对加密结果做Base64转换,在解密之前要做Base64逆转换。上代码:
import android.text.TextUtils;
import android.util.Base64;
import android.util.Base64;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESUtil {
private final static String HEX = "0123456789ABCDEF";
private static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";//AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式
private static final String AES = "AES";//AES 加密
private static final String SHA1PRNG = "SHA1PRNG";// SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法
private static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";//AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式
private static final String AES = "AES";//AES 加密
private static final String SHA1PRNG = "SHA1PRNG";// SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法
/*
*生成密钥,加密和解密的密钥必须一致,不然将不能解密
*/
public static String generateKey() {
try {
SecureRandom secureRandom = SecureRandom.getInstance(SHA1PRNG);
byte[] key = new byte[20];
secureRandom.nextBytes(key);
return toHex(key);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
*生成密钥,加密和解密的密钥必须一致,不然将不能解密
*/
public static String generateKey() {
try {
SecureRandom secureRandom = SecureRandom.getInstance(SHA1PRNG);
byte[] key = new byte[20];
secureRandom.nextBytes(key);
return toHex(key);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 对密钥进行处理
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
SecureRandom sr = null;
// 在4.2以上版本中,SecureRandom获取方式发生了改变
if (android.os.Build.VERSION.SDK_INT >= 17) {
sr = SecureRandom.getInstance(SHA1PRNG, new CryptoProvider());
} else {
sr = SecureRandom.getInstance(SHA1PRNG);
}
sr.setSeed(seed);
keyGenerator.init(128, sr);//256 bits or 128 bits,192bits
//AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥
// 版本则有14个加密循环。
return keyGenerator.generateKey().getEncoded();
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
SecureRandom sr = null;
// 在4.2以上版本中,SecureRandom获取方式发生了改变
if (android.os.Build.VERSION.SDK_INT >= 17) {
sr = SecureRandom.getInstance(SHA1PRNG, new CryptoProvider());
} else {
sr = SecureRandom.getInstance(SHA1PRNG);
}
sr.setSeed(seed);
keyGenerator.init(128, sr);//256 bits or 128 bits,192bits
//AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥
// 版本则有14个加密循环。
return keyGenerator.generateKey().getEncoded();
}
/**
* 加密
*
* @param key 密钥
* @param plaintext 明文
* @return
*/
public static String encrypt(String key, String plaintext) {
if (TextUtils.isEmpty(plaintext)) {
return plaintext;
}
try {
byte[] result = encrypt(key, plaintext.getBytes("UTF-8"));
return new String(Base64.encode(result, Base64.DEFAULT));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
* 加密
*
* @param key 密钥
* @param plaintext 明文
* @return
*/
public static String encrypt(String key, String plaintext) {
if (TextUtils.isEmpty(plaintext)) {
return plaintext;
}
try {
byte[] result = encrypt(key, plaintext.getBytes("UTF-8"));
return new String(Base64.encode(result, Base64.DEFAULT));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 加密
*
* @param key
* @param ciphertext
* @return
* @throws Exception
*/
private static byte[] encrypt(String key, byte[] ciphertext) throws Exception {
byte[] raw = getRawKey(key.getBytes());
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,
new IvParameterSpec(new byte[cipher.getBlockSize()]));
return cipher.doFinal(ciphertext);
}
* 加密
*
* @param key
* @param ciphertext
* @return
* @throws Exception
*/
private static byte[] encrypt(String key, byte[] ciphertext) throws Exception {
byte[] raw = getRawKey(key.getBytes());
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,
new IvParameterSpec(new byte[cipher.getBlockSize()]));
return cipher.doFinal(ciphertext);
}
/**
* 二进制转字符
*
* @param buf
* @return
*/
public static String toHex(byte[] buf) {
if (buf == null) {
return "";
}
StringBuffer result = new StringBuffer(2 * buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
* 二进制转字符
*
* @param buf
* @return
*/
public static String toHex(byte[] buf) {
if (buf == null) {
return "";
}
StringBuffer result = new StringBuffer(2 * buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
/**
* 解密
*
* @param key 密钥
* @param ciphertext 密文
* @return
*/
public static String decrypt(String key, String ciphertext) {
if (TextUtils.isEmpty(ciphertext)) {
return ciphertext;
}
try {
byte[] enc = Base64.decode(ciphertext.getBytes("UTF-8"), Base64.DEFAULT);
byte[] result = decrypt(key, enc);
return new String(result);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
* 解密
*
* @param key 密钥
* @param ciphertext 密文
* @return
*/
public static String decrypt(String key, String ciphertext) {
if (TextUtils.isEmpty(ciphertext)) {
return ciphertext;
}
try {
byte[] enc = Base64.decode(ciphertext.getBytes("UTF-8"), Base64.DEFAULT);
byte[] result = decrypt(key, enc);
return new String(result);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 真正解密
*
* @param key 密钥
* @param ciphertext 密文
* @return
*/
private static byte[] decrypt(String key, byte[] ciphertext) {
try {
byte[] raw = getRawKey(key.getBytes());
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec,
new IvParameterSpec(new byte[cipher.getBlockSize()]));
return cipher.doFinal(ciphertext);
} catch (Exception e) {
e.printStackTrace();
}
* 真正解密
*
* @param key 密钥
* @param ciphertext 密文
* @return
*/
private static byte[] decrypt(String key, byte[] ciphertext) {
try {
byte[] raw = getRawKey(key.getBytes());
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec,
new IvParameterSpec(new byte[cipher.getBlockSize()]));
return cipher.doFinal(ciphertext);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
static final class CryptoProvider extends Provider {
/**
* Creates a Provider and puts parameters
*/
public CryptoProvider() {
super("Crypto", 1.0, "HARMONY (SHA1 digest; SecureRandom; SHA1withDSA signature)");
put("SecureRandom.SHA1PRNG", "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl");
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
}
/**
* Creates a Provider and puts parameters
*/
public CryptoProvider() {
super("Crypto", 1.0, "HARMONY (SHA1 digest; SecureRandom; SHA1withDSA signature)");
put("SecureRandom.SHA1PRNG", "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl");
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
}
}
}
public class TestActivity extends Activity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); String key = AESUtil.generateKey(); Log.e("TestActivity", "key " + key); String content = AESUtil.encrypt(key, "测试AES OK!"); Log.e("TestActivity", "加密后 " + content); String ss = AESUtil.decrypt(key, content); Log.e("TestActivity", "解密后 " + ss); } }
}