/**
* 常用的加密算法
*/
public final class CryptUtil {
private CryptUtil(){}
///////////////////////////////////////////////////////////////////////////
// DES
///////////////////////////////////////////////////////////////////////////
/**
* DES 加密算法
* @param data 原始数据
* @param key 密码,必须是8个字节
* @return byte[] 经过加密之后的内容
*/
public static byte[] desEncrypt(byte[] data, byte[] key){
byte[] ret = null;
if (data != null && key != null) {
if(data.length > 0 && key.length == 8){
// 1. 使用 Cipher 引擎 来初始化 加密,并且设置密码
try {
Cipher cipher = Cipher.getInstance("DES");
// 1.1 DESKeySpec 用于描述DES的密码
DESKeySpec spec = new DESKeySpec(key);
// 1.2 使用 SecretKeyFactory 生成 Key对象
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKey sk = factory.generateSecret(spec);
// 1.3 初始化 Cipher 为加密操作,并且指定密钥
cipher.init(Cipher.ENCRYPT_MODE, sk);
// 2. 加密数据
ret = cipher.doFinal(data);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
}
return ret;
}
/**
* DES 解密算法
* @param data 原始数据
* @param key 密码,必须是8个字节
* @return byte[] 经过解密之后的内容
*/
public static byte[] desDecrypt(byte[] data, byte[] key){
byte[] ret = null;
if (data != null && key != null) {
if(data.length > 0 && key.length == 8){
// 1. 使用 Cipher 引擎 来初始化 解密,并且设置密码
try {
Cipher cipher = Cipher.getInstance("DES");
// 1.1 DESKeySpec 用于描述DES的密码
DESKeySpec spec = new DESKeySpec(key);
// 1.2 使用 SecretKeyFactory 生成 Key对象
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKey sk = factory.generateSecret(spec);
// 1.3 初始化 Cipher 为解密操作,并且指定密钥
cipher.init(Cipher.DECRYPT_MODE, sk);
// 2. 解密数据
ret = cipher.doFinal(data);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
}
return ret;
}
///////////////////////////////////////////////////////////////////////////
// AES 方式1
///////////////////////////////////////////////////////////////////////////
public static byte[] aesEncryptSimple(byte[] data, byte[] key){
byte[] ret = null;
if (data != null && key != null) {
if(data.length > 0 && key.length == 16){
// AES 128bit = 16bytes
try {
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
ret = cipher.doFinal(data);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
}
return ret;
}
public static byte[] aesDecryptSimple(byte[] data, byte[] key){
byte[] ret = null;
if (data != null && key != null) {
if(data.length > 0 && key.length == 16){
// AES 128bit = 16bytes
try {
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
ret = cipher.doFinal(data);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
}
return ret;
}
///////////////////////////////////////////////////////////////////////////
// AES 方式2 使用两套密码
///////////////////////////////////////////////////////////////////////////
/**
* 使用两套密码的加密,强度更高
* @param data 数据
* @param key 第一个密码
* @param ivData 第二个密码
* @return byte[]
*/
public static byte[] aesEncryptWithIv(byte[] data, byte[] key, byte[] ivData){
byte[] ret = null;
if (data != null && key != null && ivData != null) {
if(data.length > 0 && key.length == 16 && ivData.length == 16){
// 使用两套密码的,算法需要写成 AES/算法模式/填充模式
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 准备第一套密码
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
// 准备第二套密码
IvParameterSpec iv = new IvParameterSpec(ivData);
// 设置两套密码的初始化
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
cipher.update(data);
ret = cipher.doFinal();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
}
return ret;
}
public static byte[] aesDecryptWithIv(byte[] data, byte[] key, byte[] ivData){
byte[] ret = null;
if (data != null && key != null && ivData != null) {
if(data.length > 0 && key.length == 16 && ivData.length == 16){
// 使用两套密码的,算法需要写成 AES/算法模式/填充模式
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 准备第一套密码
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
// 准备第二套密码
IvParameterSpec iv = new IvParameterSpec(ivData);
// 设置两套密码的初始化
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
cipher.update(data);
ret = cipher.doFinal();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
}
return ret;
}
///////////////////////////////////////////////////////////////////////////
// RSA
///////////////////////////////////////////////////////////////////////////
// 1. 生成密钥对 公钥和私钥
/**
*
* @param bits 必须在 1024,2048
* @return
*/
public static KeyPair generateRsaKey(int bits){
KeyPair ret = null;
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(bits);
ret = kpg.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return ret;
}
/**
* RSA加密,使用公钥加密,那么必须使用私钥解密
* 使用私钥机密,那么必须使用公钥解密
* @param data
* @param key
* @return
*/
public static byte[] rsaEncrypt(byte[] data, Key key){
byte[] ret = null;
if (data != null && data.length > 0 && key != null) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, key);
ret = cipher.doFinal(data);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
return ret;
}
public static byte[] rsaDecrypt(byte[] data, Key key){
byte[] ret = null;
if (data != null && data.length > 0 && key != null) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, key);
ret = cipher.doFinal(data);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
return ret;
}
}
2.MainActivity
public class MainActivity extends AppCompatActivity {
private EditText mTextContent;
private TextView mTextResult;
private EditText mTextPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextContent = (EditText) findViewById(R.id.txt_content);
mTextResult = (TextView) findViewById(R.id.txt_result);
mTextPassword = (EditText) findViewById(R.id.txt_password);
}
public void btnBase64Encode(View view) {
String str = mTextContent.getText().toString().trim();
// Base64 编码,NO_WRAP 代表编码的结果没有任何换行
String encoded = Base64.encodeToString(str.getBytes(), Base64.NO_WRAP);
mTextResult.setText(encoded);
// Base64 解码,
String es = "5pKS5Zyw5pa55Y+r6ICD5ouJ5rC05reA57KJ5Y2z5Y+v5ouJ5rC05reA57KJ5Y2z5Y+v55qE6aOO5pmv5Y2h5omL5py65Y+R55qE5Y2h5ouJ55qE";
byte[] decode = Base64.decode(es, Base64.NO_WRAP);
String ss = null;
try {
ss = new String(decode, "UTF-8");
Log.d("Base64", "ss = " + ss);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void btnUrlEncoding(View view) {
String str = "%B1%E4%D0%CE%BD%F0%B8%D5";
try {
String decode = URLDecoder.decode(str, "GBK");
Log.d("UE", "btnUrlEncoding: " + decode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// URLEncoder 编码内容为可以在网址上拼接的字符串
try {
String ss = URLEncoder.encode("张哥Very很帅", "UTF-8");
Log.d("UE", "btnUrlEncoding: ss = " + ss);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* GZIP 压缩、解压缩
*
* @param view
*/
public void btnGzipTest(View view) {
String str = mTextContent.getText().toString().trim();
// 1. 压缩GZIP, GZIPOutputStream
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try {
GZIPOutputStream gzOut = new GZIPOutputStream(bout);
gzOut.write(str.getBytes()); // 利用GZIPOutputStream 压缩,并且输出结果
gzOut.finish(); // 必须调用,在结束的时候,生成实际的压缩数据
gzOut.close();
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = bout.toByteArray();
mTextResult.setText("内容长度:" + str.length() + "\n压缩大小: " + data.length);
String s = Arrays.toString(data);
Log.d("GZIP", "btnGzipTest: " + s);
// 解压缩 GZIPInputStream
ByteArrayInputStream bin = new ByteArrayInputStream(data);
try {
GZIPInputStream gzIn = new GZIPInputStream(bin);
ByteArrayOutputStream bo = new ByteArrayOutputStream();
byte[] buf = new byte[128];
int len;
while (true) {
len = gzIn.read(buf);
if (len == -1) {
break;
}
bo.write(buf, 0, len);
}
byte[] bytes = bo.toByteArray();
String ss = new String(bytes);
Log.d("GZIP", "btnGzipTest: gzip ss = " + ss);
} catch (IOException e) {
e.printStackTrace();
}
}
public void btnDesTest(View view) {
// DES test
String str = mTextContent.getText().toString().trim();
String pwd = mTextPassword.getText().toString().trim();
// byte[] encrypt = CryptUtil.desEncrypt(str.getBytes(), pwd.getBytes());
byte[] iv = {23, 33, 2, 3, 3, 4, 6, 7, 1, 3, 3, 4, 4, 3, 4, 4};
byte[] encrypt = CryptUtil.aesEncryptWithIv(str.getBytes(), pwd.getBytes(), iv);
String s = Base64.encodeToString(encrypt, Base64.NO_WRAP);
mTextResult.setText(s);
// 解密,把Base64 字符串 还原并且解密
byte[] ed = Base64.decode(s, Base64.NO_WRAP);
// byte[] data = CryptUtil.desDecrypt(ed, pwd.getBytes());
byte[] data = CryptUtil.aesDecryptWithIv(ed, pwd.getBytes(), iv);
String ss = new String(data);
Log.d("DES", "btnDesTest: " + ss);
}
public void btnRsaTest(View view) {
// 1. 加载/生成 密钥对
KeyPair keyPair = CryptUtil.generateRsaKey(1024);
// 私钥
PrivateKey aPrivate = keyPair.getPrivate();
// 公钥
PublicKey aPublic = keyPair.getPublic();
// TODO: 把公钥、私钥 使用 Base64编码,保存到文件中;下一次启动的时候,需要先加载,没有才创建
// 私钥的数据格式
byte[] privEncoded = aPrivate.getEncoded();
// 公钥的数据格式
byte[] pubEncoded = aPublic.getEncoded();
String str = mTextContent.getText().toString().trim();
byte[] encrypt = CryptUtil.rsaEncrypt(str.getBytes(), aPublic);
String es = Base64.encodeToString(encrypt, Base64.NO_WRAP);
mTextResult.setText(es);
byte[] dd = Base64.decode(es, Base64.NO_WRAP);
byte[] data = CryptUtil.rsaDecrypt(dd, aPrivate);
String s = new String(data);
Log.d("RSA", "btnRsaTest: " + s);
}
}