在 Android 开发中,数据的安全性非常重要,尤其是敏感数据的存储和传输。为了实现数据加密和解密,我们可以封装一个通用的加解密工具类,支持常见的加密算法(如 AES、RSA、DES 等)。以下是一个基于 AES 对称加密算法的工具类封装示例,同时提供扩展性以支持其他算法。
- AES 加解密工具类封装
AES(Advanced Encryption Standard)是一种对称加密算法,加密和解密使用相同的密钥。以下是封装好的工具类:
import android.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;public class AESUtil {private static final String ALGORITHM = "AES";private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding"; // AES 加密模式和填充方式/*** 加密** @param data 待加密的数据* @param key 密钥(必须是 16、24 或 32 字节)* @return 加密后的 Base64 编码字符串*/public static String encrypt(String data, String key) {try {SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);Cipher cipher = Cipher.getInstance(TRANSFORMATION);cipher.init(Cipher.ENCRYPT_MODE, secretKey);byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));return Base64.encodeToString(encryptedBytes, Base64.DEFAULT);} catch (Exception e) {e.printStackTrace();return null;}}/*** 解密** @param encryptedData 加密后的 Base64 编码字符串* @param key 密钥(必须是 16、24 或 32 字节)* @return 解密后的原始数据*/public static String decrypt(String encryptedData, String key) {try {SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);Cipher cipher = Cipher.getInstance(TRANSFORMATION);cipher.init(Cipher.DECRYPT_MODE, secretKey);byte[] decryptedBytes = cipher.doFinal(Base64.decode(encryptedData, Base64.DEFAULT));return new String(decryptedBytes, StandardCharsets.UTF_8);} catch (Exception e) {e.printStackTrace();return null;}}
}
使用示例
public class Main {public static void main(String[] args) {String originalData = "Hello, AES Encryption!";String key = "1234567890123456"; // 密钥必须是 16、24 或 32 字节// 加密String encryptedData = AESUtil.encrypt(originalData, key);System.out.println("加密后的数据: " + encryptedData);// 解密String decryptedData = AESUtil.decrypt(encryptedData, key);System.out.println("解密后的数据: " + decryptedData);}
}
2.RSA 加解密工具类封装
RSA 是一种非对称加密算法,使用公钥加密、私钥解密。以下是 RSA 工具类的简单实现:
import android.util.Base64;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;public class RSAUtil {private static final String ALGORITHM = "RSA";/*** 生成 RSA 密钥对** @return 生成的密钥对*/public static KeyPair generateKeyPair() throws Exception {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);keyPairGenerator.initialize(2048); // 密钥长度return keyPairGenerator.generateKeyPair();}/*** 使用公钥加密** @param data 待加密的数据* @param publicKey 公钥* @return 加密后的 Base64 编码字符串*/public static String encrypt(String data, PublicKey publicKey) throws Exception {Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] encryptedBytes = cipher.doFinal(data.getBytes());return Base64.encodeToString(encryptedBytes, Base64.DEFAULT);}/*** 使用私钥解密** @param encryptedData 加密后的 Base64 编码字符串* @param privateKey 私钥* @return 解密后的原始数据*/public static String decrypt(String encryptedData, PrivateKey privateKey) throws Exception {Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] decryptedBytes = cipher.doFinal(Base64.decode(encryptedData, Base64.DEFAULT));return new String(decryptedBytes);}/*** 将 Base64 编码的公钥字符串转换为 PublicKey 对象** @param base64PublicKey Base64 编码的公钥字符串* @return PublicKey 对象*/public static PublicKey getPublicKey(String base64PublicKey) throws Exception {byte[] keyBytes = Base64.decode(base64PublicKey, Base64.DEFAULT);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);return keyFactory.generatePublic(keySpec);}/*** 将 Base64 编码的私钥字符串转换为 PrivateKey 对象** @param base64PrivateKey Base64 编码的私钥字符串* @return PrivateKey 对象*/public static PrivateKey getPrivateKey(String base64PrivateKey) throws Exception {byte[] keyBytes = Base64.decode(base64PrivateKey, Base64.DEFAULT);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);return keyFactory.generatePrivate(keySpec);}/*** 将公钥对象转换为 Base64 编码字符串** @param publicKey 公钥对象* @return Base64 编码的公钥字符串*/public static String getPublicKeyString(PublicKey publicKey) {return Base64.encodeToString(publicKey.getEncoded(), Base64.DEFAULT);}/*** 将私钥对象转换为 Base64 编码字符串** @param privateKey 私钥对象* @return Base64 编码的私钥字符串*/public static String getPrivateKeyString(PrivateKey privateKey) {return Base64.encodeToString(privateKey.getEncoded(), Base64.DEFAULT);}
}
使用示例:
import java.security.KeyPair;public class Main {public static void main(String[] args) {try {// 1. 生成密钥对KeyPair keyPair = RSAUtil.generateKeyPair();String publicKeyString = RSAUtil.getPublicKeyString(keyPair.getPublic());String privateKeyString = RSAUtil.getPrivateKeyString(keyPair.getPrivate());System.out.println("公钥: " + publicKeyString);System.out.println("私钥: " + privateKeyString);// 2. 加密数据String originalData = "Hello, RSA Encryption!";String encryptedData = RSAUtil.encrypt(originalData, keyPair.getPublic());System.out.println("加密后的数据: " + encryptedData);// 3. 解密数据String decryptedData = RSAUtil.decrypt(encryptedData, keyPair.getPrivate());System.out.println("解密后的数据: " + decryptedData);} catch (Exception e) {e.printStackTrace();}}
}
输出示例:
公钥: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1X7...
私钥: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBA...
加密后的数据: jKlQmZ2P3X7v...
解密后的数据: Hello, RSA Encryption!
工具类的功能说明
生成密钥对:
使用 generateKeyPair() 方法生成 RSA 密钥对(公钥和私钥)。
公钥用于加密,私钥用于解密。
加密数据:
使用 encrypt() 方法,传入原始数据和公钥,返回加密后的 Base64 编码字符串。
解密数据:
使用 decrypt() 方法,传入加密后的 Base64 编码字符串和私钥,返回解密后的原始数据。
密钥转换:
支持将 PublicKey 和 PrivateKey 对象转换为 Base64 编码字符串,便于存储和传输。
支持将 Base64 编码的密钥字符串转换回 PublicKey 或 PrivateKey 对象。
注意事项
密钥长度:
RSA 密钥长度通常为 2048 位或更高,以确保安全性。
加密数据大小限制:
RSA 加密的数据大小受密钥长度限制。例如,2048 位密钥最多只能加密 245 字节的数据。如果需要加密更大的数据,可以结合对称加密(如 AES)使用。
密钥存储:
私钥必须妥善保存,避免泄露。可以使用 Android Keystore 系统来安全存储密钥。
性能:
RSA 加密和解密速度较慢,适合加密小数据(如密钥或敏感信息)。
3. MD5 工具类封装
MD5 是一种广泛使用的哈希算法,通常用于生成数据的唯一摘要(哈希值)。虽然 MD5 不再推荐用于加密(因为它容易受到碰撞攻击),但它仍然可以用于校验数据完整性或生成唯一标识。以下是 MD5 工具类的封装,并附带使用示例。
代码:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class MD5Util {/*** 生成字符串的 MD5 哈希值** @param input 输入字符串* @return MD5 哈希值(32 位十六进制字符串)*/public static String md5(String input) {try {// 创建 MessageDigest 实例,指定使用 MD5 算法MessageDigest digest = MessageDigest.getInstance("MD5");// 将输入字符串转换为字节数组并计算哈希值byte[] hashBytes = digest.digest(input.getBytes());// 将字节数组转换为十六进制字符串StringBuilder hexString = new StringBuilder();for (byte b : hashBytes) {String hex = Integer.toHexString(0xff & b);if (hex.length() == 1) {hexString.append('0');}hexString.append(hex);}return hexString.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();return null;}}/*** 生成文件的 MD5 哈希值** @param filePath 文件路径* @return 文件的 MD5 哈希值(32 位十六进制字符串)*/public static String md5File(String filePath) {try {MessageDigest digest = MessageDigest.getInstance("MD5");FileInputStream fis = new FileInputStream(filePath);byte[] buffer = new byte[8192];int bytesRead;while ((bytesRead = fis.read(buffer)) != -1) {digest.update(buffer, 0, bytesRead);}fis.close();// 将字节数组转换为十六进制字符串byte[] hashBytes = digest.digest();StringBuilder hexString = new StringBuilder();for (byte b : hashBytes) {String hex = Integer.toHexString(0xff & b);if (hex.length() == 1) {hexString.append('0');}hexString.append(hex);}return hexString.toString();} catch (Exception e) {e.printStackTrace();return null;}}
}
使用示例
示例 1:计算字符串的 MD5 哈希值
public class Main {public static void main(String[] args) {String input = "Hello, MD5!";String md5Hash = MD5Util.md5(input);System.out.println("MD5 哈希值: " + md5Hash);}
}
输出结果:
MD5 哈希值: ed076287532e86365e841e92bfc50d8c
示例 2:计算文件的 MD5 哈希值:
public class Main {public static void main(String[] args) {String filePath = "path/to/your/file.txt";String md5Hash = MD5Util.md5File(filePath);System.out.println("文件的 MD5 哈希值: " + md5Hash);}
}
输出结果:
文件的 MD5 哈希值: d41d8cd98f00b204e9800998ecf8427e
工具类的功能说明
字符串 MD5 哈希:
md5(String input) 方法用于计算输入字符串的 MD5 哈希值。
返回一个 32 位的十六进制字符串。
文件 MD5 哈希:
md5File(String filePath) 方法用于计算文件的 MD5 哈希值。
适用于校验文件完整性或生成文件的唯一标识。
异常处理:
如果算法不可用(NoSuchAlgorithmException),会捕获异常并返回 null。
文件操作异常(如文件不存在)也会被捕获并返回 null。