【Android】Android加密和解密方式

tech2025-09-07  14

一、不可逆加密

不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。 如信息摘要(Message Digest)和安全散列(Secure Hash)算法属于此类,常见的算法包括 MD5、SHA1、PBKDF2、bcrypt 等。 特点: 使用MD5和SHA进行加解密:

// MD5加密 private static String toMd5(String str) { // 实例化一个指定摘要算法为MD5的MessageDigest对象 MessageDigest algorithm; try { algorithm = MessageDigest.getInstance("MD5"); // 重置摘要以供再次使用 algorithm.reset(); // 使用bytes更新摘要 algorithm.update(str.getBytes()); // 使用指定的byte数组对摘要进行最后更新,然后完成摘要计算 return toHexString(algorithm.digest(), ""); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null; } // SHA加密 private static String toSHA(String str) { // 实例化一个指定摘要算法为SHA的MessageDigest对象 MessageDigest algorithm; try { algorithm = MessageDigest.getInstance("SHA"); // 重置摘要以供再次使用 algorithm.reset(); // 使用bytes更新摘要 algorithm.update(str.getBytes()); // 使用指定的byte数组对摘要进行最后更新,然后完成摘要计算 return toHexString(algorithm.digest(), ""); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null; } // 将字符串中的每个字符转换为十六进制 private static String toHexString(byte[] bytes, String separtor) { StringBuilder hexString = new StringBuilder(); for (byte b : bytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) { hexString.append("0"); } hexString.append(hex).append(separtor); } return hexString.toString(); }

二、可逆加密

算法加密

基于算法的加密算法,也被称为古典加密算法,如 HTTP 认证中的 base64,是一种基于64个基本字符,加密后的内容只包含这64个字符,加密后长度会变大。它是最简单的一种算法,一般用于加密URL. 下图为Base64编码表

Base64加解密相关代码

// 需要引入包:java.util.Base64 // Base64加密 private static String encode(String str) { byte[] encodeBytes = Base64.getEncoder().encode(str.getBytes()); return new String(encodeBytes); } // Base64解密 private static String decode(String str) { byte[] decodeBytes = Base64.getDecoder().decode(str.getBytes()); return new String(decodeBytes); }

对称加密

对称加密:加密和解密的密钥一样。常见的对称加密算法有 DES、3DES、AES。这三者的关系可以理解为迭代和替代。3DES是对DES的发展,AES是为了替代DES. DES加解密相关代码

public class DESUtil { // 初始化向量 private static byte[] iv = { 'a', 'b', 'c', 'd', 'e', 1, 2, '*' }; // DES加密 // encryptText为原文 // encryptKey为密匙 private static String encryptDES(String encryptText, String encryptKey) throws Exception { // 实例化IvParameterSpec对象,使用指定的初始化向量 IvParameterSpec spec = new IvParameterSpec(iv); // 实例化SecretKeySpec类,根据字节数组来构造SecretKeySpec SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "DES"); // 创建密码器 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); // 用密码初始化Cipher对象 cipher.init(Cipher.ENCRYPT_MODE, key, spec); // 执行加密操作 byte[] encryptData = cipher.doFinal(encryptText.getBytes()); // 返回加密后的数据 return Base64.getEncoder().encodeToString(encryptData); } // 解密 private static String decryptDES(String decryptString, String decryptKey) throws Exception { // 先使用Base64解密 byte[] base64byte = Base64.getDecoder().decode(decryptString); // 实例化IvParameterSpec对象,使用指定的初始化向量 IvParameterSpec spec = new IvParameterSpec(iv); // 实例化SecretKeySpec类,根据字节数组来构造SecretKeySpec SecretKeySpec key = new SecretKeySpec(decryptKey.getBytes(), "DES"); // 创建密码器 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); // 用密码初始化Cipher对象 cipher.init(Cipher.DECRYPT_MODE, key, spec); // 获取解密后的数据 byte decryptedData[] = cipher.doFinal(base64byte); // 将解密后数据转换为字符串输出 return new String(decryptedData); } }

AES加解密相关代码

public class AESUtil { // 采用对称分组密码体制,密钥长度的最少支持为128、192、256 String key = "abcdefghijklmnop"; // 初始化向量参数,AES 为16bytes. DES 为8bytes, 16*8=128 String initVector = "0000000000000000"; IvParameterSpec iv; SecretKeySpec skeySpec; Cipher cipher; private static class HOLDER { private static AESUtil instance = new AESUtil(); } public static AESUtil getInstance() { return HOLDER.instance; } private AESUtil() { try { iv = new IvParameterSpec(initVector.getBytes("UTF-8")); skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); // 这是CBC模式 // cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); // 默认就是ECB模式 cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } public String encrypt(String value) { try { // CBC模式需要传入向量,ECB模式不需要 // cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(value.getBytes()); return Base64.encodeToString(encrypted, Base64.DEFAULT); } catch (Exception e) { e.printStackTrace(); } return null; } public String decrypt(String encrypted) { try { // CBC模式需要传入向量,ECB模式不需要 // cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] original = cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT)); return new String(original); } catch (Exception ex) { ex.printStackTrace(); } return null; }

非对称加密

非对称加密:加密和解密的密钥不同,通常是公钥加密私钥解密,当然也可以私钥加密公钥解密,公钥通常用来对内容加密,而私钥既可以解密也可以用来确定是否是对应的公钥加的密,防止他人用错误的公钥进行加密。 非对称加密中另外两个重要的概念是公钥和私钥。公钥对外公开,任何人均可持有和使用;私钥自行保管,其安全性是通信安危的关键。常见的算法有 RSA、DH(Diffie-Hellman)、椭圆曲线算法(Elliptic curve cryptography,ECC)。 私钥和公钥的作用一般分为两种: 公钥加密,私钥解密,主要用于通信; 私钥加密(签名),公钥解密(验证),主要用于数字签名。 RSA算法相关代码

public class RSAUtil { public static final String RSA = "RSA"; public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding"; // 秘钥默认长度 public static final int DEFAULT_KEY_SIZE = 2048; // 当要加密的内容超过bufferSize,则采用partSplit进行分块加密 public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes(); // 当前秘钥支持加密的最大字节数 public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11; // 随机生成RSA密钥对,密钥长度,范围:512~2048 public static KeyPair generateRSAKeyPair(int keyLength) { try { KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA); kpg.initialize(keyLength); return kpg.genKeyPair(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } /** * 私钥加密 * @param data 待加密数据 * @param privateKey 密钥 * @return byte[] 加密数据 */ public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception { // 得到私钥 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance(RSA); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 数据加密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.ENCRYPT_MODE, keyPrivate); return cipher.doFinal(data); } // 使用私钥进行解密 public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception { // 得到私钥 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance(RSA); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 解密数据 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.DECRYPT_MODE, keyPrivate); byte[] arr = cp.doFinal(encrypted); return arr; } // 用公钥对字符串进行加密 public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公钥 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 加密数据 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.ENCRYPT_MODE, keyPublic); return cp.doFinal(data); } /** * 公钥解密 * @param data 待解密数据 * @param publicKey 密钥 * @return byte[] 解密数据 */ public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公钥 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 数据解密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.DECRYPT_MODE, keyPublic); return cipher.doFinal(data); } // 以下开始分段解密 // 使用私钥分段解密 public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception { int splitLen = DEFAULT_SPLIT.length; if (splitLen <= 0) { return decryptByPrivateKey(encrypted, privateKey); } int dataLen = encrypted.length; List<Byte> allBytes = new ArrayList<Byte>(1024); int latestStartIndex = 0; for (int i = 0; i < dataLen; i++) { byte bt = encrypted[i]; boolean isMatchSplit = false; if (i == dataLen - 1) { // 到data的最后了 byte[] part = new byte[dataLen - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPrivateKey(part, privateKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } else if (bt == DEFAULT_SPLIT[0]) { // 这个是以split[0]开头 if (splitLen > 1) { if (i + splitLen < dataLen) { // 没有超出data的范围 for (int j = 1; j < splitLen; j++) { if (DEFAULT_SPLIT[j] != encrypted[i + j]) { break; } if (j == splitLen - 1) { // 验证到split的最后一位,都没有break,则表明已经确认是split段 isMatchSplit = true; } } } } else { // split只有一位,则已经匹配了 isMatchSplit = true; } } if (isMatchSplit) { byte[] part = new byte[i - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPrivateKey(part, privateKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } // 私钥分段加密 public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception { int dataLen = data.length; if (dataLen <= DEFAULT_BUFFERSIZE) { return encryptByPrivateKey(data, privateKey); } List<Byte> allBytes = new ArrayList<Byte>(2048); int bufIndex = 0; int subDataLoop = 0; byte[] buf = new byte[DEFAULT_BUFFERSIZE]; for (int i = 0; i < dataLen; i++) { buf[bufIndex] = data[i]; if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { subDataLoop++; if (subDataLoop != 1) { for (byte b : DEFAULT_SPLIT) { allBytes.add(b); } } byte[] encryptBytes = encryptByPrivateKey(buf, privateKey); for (byte b : encryptBytes) { allBytes.add(b); } bufIndex = 0; if (i == dataLen - 1) { buf = null; } else { buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; } } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } // 用公钥对字符串进行分段加密 public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception { int dataLen = data.length; if (dataLen <= DEFAULT_BUFFERSIZE) { return encryptByPublicKey(data, publicKey); } List<Byte> allBytes = new ArrayList<Byte>(2048); int bufIndex = 0; int subDataLoop = 0; byte[] buf = new byte[DEFAULT_BUFFERSIZE]; for (int i = 0; i < dataLen; i++) { buf[bufIndex] = data[i]; if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { subDataLoop++; if (subDataLoop != 1) { for (byte b : DEFAULT_SPLIT) { allBytes.add(b); } } byte[] encryptBytes = encryptByPublicKey(buf, publicKey); for (byte b : encryptBytes) { allBytes.add(b); } bufIndex = 0; if (i == dataLen - 1) { buf = null; } else { buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; } } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } // 公钥分段解密 public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception { int splitLen = DEFAULT_SPLIT.length; if (splitLen <= 0) { return decryptByPublicKey(encrypted, publicKey); } int dataLen = encrypted.length; List<Byte> allBytes = new ArrayList<Byte>(1024); int latestStartIndex = 0; for (int i = 0; i < dataLen; i++) { byte bt = encrypted[i]; boolean isMatchSplit = false; if (i == dataLen - 1) { // 到data的最后了 byte[] part = new byte[dataLen - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPublicKey(part, publicKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } else if (bt == DEFAULT_SPLIT[0]) { // 这个是以split[0]开头 if (splitLen > 1) { if (i + splitLen < dataLen) { // 没有超出data的范围 for (int j = 1; j < splitLen; j++) { if (DEFAULT_SPLIT[j] != encrypted[i + j]) { break; } if (j == splitLen - 1) { // 验证到split的最后一位,都没有break,则表明已经确认是split段 isMatchSplit = true; } } } } else { // split只有一位,则已经匹配了 isMatchSplit = true; } } if (isMatchSplit) { byte[] part = new byte[i - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPublicKey(part, publicKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } }
最新回复(0)