https://blog.csdn.net/u013718120/article/details/56486408
https://github.com/songxiaoliang/EncryptionLib
一、对称加密算法
对称密码算法的 加密密钥和解密密钥相同,
对于大多数对称密码算法,加解密过程互逆
AES 对 DES提高了安全性
1.DES,3DES
DES使用【56位密钥】以及附加的【8位奇偶校验位】对【64位的数据块】进行加密,
并对64位的数据块进行16轮编码。
与每轮编码时,一个48位的“每轮”密钥值由56位的完整密钥得出来。
DES 密钥有效位是 56位,还有8位是用于奇偶校验位。
DES 加密对明文是有限制的,只会对64位明文即8个字节的数据加密
3DES 使用【两个密钥】对明文进行三次加密。
假设两个密钥是K1和K2
3DES 加密过程: C=Ek3(Dk2(Ek1(M)))
1) 用密钥K1进行DES加密。
2) 用K2对步骤1的结果进行DES解密。
3) 用步骤2的结果使用密钥K1进行DES加密。
3DES 解密过程: M=Dk1(EK2(Dk3©))
1) 用密钥K1堆数据进行进行DES解密。
2) 用K2对步骤1的结果进行DES加密。
3) 用步骤2的结果使用密钥K1进行DES解密。
3DES 的缺点,是要花费原来三倍时间,优点是使用两个密钥,有效密钥长度112位。
-
优点:算法公开、计算量小、加密速度快、加密效率高
-
缺点:双方都使用同样密钥,安全性得不到保证
public class DESUtils { //生成密钥 public static byte[] generateKey() { KeyGenerator keyGen = null; try { keyGen = KeyGenerator.getInstance("DES"); // 秘钥生成器 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } keyGen.init(64); //初始密钥生成器,DES使用56位密钥 SecretKey secretKey = keyGen.generateKey(); // 生成秘钥 return secretKey.getEncoded(); // 获取秘钥字节数组 } //加密 public static byte[] encrypt(byte[] data, byte[] key) { SecretKey secretKey = new SecretKeySpec(key, "DES"); // 恢复秘钥 Cipher cipher = null; byte[] cipherBytes = null; try { cipher = Cipher.getInstance("DES"); // 对Cipher完成加密或解密工作 cipher.init(Cipher.ENCRYPT_MODE, secretKey); // 对Cipher初始化,加密模式 cipherBytes = cipher.doFinal(data); // 加密数据 } catch (Exception e) { e.printStackTrace(); } return cipherBytes; } //解密 public static byte[] decrypt(byte[] data, byte[] key) { SecretKey secretKey = new SecretKeySpec(key, "DES"); // 恢复秘钥 Cipher cipher = null; byte[] plainBytes = null; try { cipher = Cipher.getInstance("DES"); // 对Cipher初始化,加密模式 cipher.init(Cipher.DECRYPT_MODE, secretKey); // 对Cipher初始化,加密模式 plainBytes = cipher.doFinal(data); // 解密数据 } catch (Exception e) { e.printStackTrace(); } return plainBytes; } }
2.AES
AES 为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等。
每次加密一组数据,直到加密完整个明文。
在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。
密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同。
AES | 密钥长度 | 分组长度 | 加密轮数 |
---|---|---|---|
AES-128 | 16 byte | 16 byte | 10 |
AES-192 | 24 byte | 16 byte | 12 |
AES-256 | 32 byte | 16 byte | 14 |
-
优点:算法公开、计算量小、加密速度快、加密效率高
-
缺点:双方都使用同样密钥,安全性得不到保证
public class AESUtils { //生成秘钥 public static byte[] generateKey() { KeyGenerator keyGen = null; try { keyGen = KeyGenerator.getInstance("AES"); // 秘钥生成器 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } keyGen.init(256); // 初始秘钥生成器 AES-256 SecretKey secretKey = keyGen.generateKey(); // 生成秘钥 return secretKey.getEncoded(); // 获取秘钥字节数组 } //加密 public static byte[] encrypt(byte[] data, byte[] key) { SecretKey secretKey = new SecretKeySpec(key, "AES"); // 恢复秘钥 Cipher cipher = null; byte[] cipherBytes = null; try { cipher = Cipher.getInstance("AES"); // 对Cipher完成加密或解密工作 cipher.init(Cipher.ENCRYPT_MODE, secretKey); // 对Cipher初始化,加密模式 cipherBytes = cipher.doFinal(data); // 加密数据 } catch (Exception e) { e.printStackTrace(); } return cipherBytes; } //解密 public static byte[] decrypt(byte[] data, byte[] key) { SecretKey secretKey = new SecretKeySpec(key, "AES"); // 恢复秘钥 Cipher cipher = null; byte[] plainBytes = null; try { cipher = Cipher.getInstance("AES"); //对Cipher初始化,加密模式 cipher.init(Cipher.DECRYPT_MODE, secretKey); //对Cipher初始化,加密模式 plainBytes = cipher.doFinal(data); // 解密数据 } catch (Exception e) { e.printStackTrace(); } return plainBytes; } //文件加密 kotlin代码 fun encryptFile(key: ByteArray?, sourceFilePath: String?, destFilePath: String?) { val sourceFile = File(sourceFilePath) val destFile = File(destFilePath) if (sourceFile.exists() && sourceFile.isFile) { var ins: InputStream? = null var ous: OutputStream? = null var cin: CipherInputStream? = null try { if (!destFile.parentFile.exists()) { destFile.parentFile.mkdirs() } destFile.createNewFile() ins = FileInputStream(sourceFile) ous = FileOutputStream(destFile) val secretKey: SecretKey = SecretKeySpec(key, ALGORITHM) val cipher = Cipher.getInstance(CIPHER_ALGORITHM) cipher.init(Cipher.ENCRYPT_MODE, secretKey) cin = CipherInputStream(ins, cipher) val cache = ByteArray(CACHE_SIZE) var nRead = 0 while (cin.read(cache).also { nRead = it } != -1) { ous.write(cache, 0, nRead) ous.flush() } } catch (e: Exception) { e.printStackTrace() } finally { ous?.close() cin?.close() ins?.close() } } } /** * 文件解密 */ fun decryptFile(key: ByteArray?, sourceFilePath: String?, destFilePath: String?) { val sourceFile = File(sourceFilePath) val destFile = File(destFilePath) if (sourceFile.exists() && sourceFile.isFile) { var ins: FileInputStream? = null var ous: FileOutputStream? = null var cout: CipherOutputStream? = null try { if (!destFile.parentFile.exists()) { destFile.parentFile.mkdirs() } destFile.createNewFile() ins = FileInputStream(sourceFile) ous = FileOutputStream(destFile) val secretKeySpec = SecretKeySpec(key, ALGORITHM) val cipher = Cipher.getInstance(CIPHER_ALGORITHM) cipher.init(Cipher.DECRYPT_MODE, secretKeySpec) cout = CipherOutputStream(ous, cipher) val cache = ByteArray(CACHE_SIZE) var nRead = 0 while (ins.read(cache).also { nRead = it } != -1) { cout.write(cache, 0, nRead) cout.flush() } } catch (e: Exception) { e.printStackTrace() } finally { cout?.close() ous?.close() ins?.close() } } } }
注意点:
1、加密后的 字节数组,不能直接转为字符串。否则会抛异常。需要转为16进制字符串来保存。
2、同时,解密时,把16进制的加密字符串,转为字节数组,然后再解密
3、关于 AES/CBC/PKCS5Padding
/*使用CBC模式,需要一个向量iv,可增加加密算法的强度
* IvParameterSpec 的参数是一个16位的字节数组,不一定是密钥
*/
val iv = IvParameterSpec(key);
cipher = Cipher.getInstance(CIPHER_ALGORITHM) // 对Cipher完成加密或解密工作
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv) // 对Cipher初始化,加密模式
二、非对称加密算法
1.RSA
最流行的公钥密码算法,使用长度可变的密钥。
既能用于数据加密也能用于数字签名的算法。
公钥加密,只能私钥解密;私钥加密,只能公钥解密。
RSA算法原理(涉及数学知识,看不懂,了解)
1)随机选择两个大质数p和q,p不等于q,计算N=pq
2)选择一个大于1小于N的自然数e,e必须与(p-1)(q-1)互素
3)用公式计算出d:d×e = 1 (mod (p-1)(q-1))
4)销毁p和q
5)最终得到的N和e就是“公钥”,d就是“私钥”,
发送方使用N去加密数据,接收方只有使用d才能解开数据内容
基于大数计算,比DES要慢上几倍,通常只能用于加密少量数据或者加密密钥。
私钥加解密都很耗时,服务器要求解密效率高,客户端私钥加密,服务器公钥解密比较好一点。
但实际操作中,比如:https、以及一些权威机构的证书,都是公钥开放出来,自己保留私钥。
实现分段加密:
RSA非对称加密内容长度有限制,1024位key的最多只能加密127位数据,
否则就会报错(javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes)
RSA 算法规定:
待加密的字节数不能超过密钥的长度值除以 8 再减去 11(即:KeySize / 8 - 11)
加密后得到密文的字节数,正好是密钥的长度值除以 8(即:KeySize / 8)
-
优点:不可逆,既能用于数据加密,也可以应用于数字签名
-
缺点:RSA非对称加密内容长度有限制,1024位key的最多只能加密127位数据
public class RSAUtils { public static final String RSA = "RSA"; // 非对称加密密钥算法 /** * android系统的RSA实现是"RSA/None/NoPadding",而标准JDK实现是"RSA/None/PKCS1Padding" , * 这造成了在android机上加密后无法在服务器上解密的原因,所以android要和服务器相同即可。 */ public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式 public static final int DEFAULT_KEY_SIZE = 2048;//秘钥默认长度 public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes();// 当要加密的内容超过bufferSize,则采用partSplit进行分块加密 public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;//当前秘钥支持加密的最大字节数 /** * 随机生成RSA密钥对 * * @param keyLength 密钥长度,范围:512~2048 * 一般1024 * 使用: * KeyPair keyPair=RSAUtils.generateRSAKeyPair(RSAUtils.DEFAULT_KEY_SIZE); * 公钥:RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); * 私钥:RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); */ 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; } } //公钥对字符串进行加密 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); } //私钥加密 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[] 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[] 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[] 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[] 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[] 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; } //私钥分段解密 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; } }
三、摘要算法
1.SHA
安全散列算法,数字签名工具。Glide在缓存key时就采用的此加密
固定长度摘要信息
包括:SHA-1
SHA-2(SHA-224,SHA-256,SHA-384,SHA-512)
SHA算法 | 摘要长度 | 实现方 |
---|---|---|
SHA-1 | 160 bit | JDK |
SHA-224(SHA-256的“阉割版) | 224 bit | Bouncy Castle |
SHA-256 | 256 bit | JDK |
SHA-384(SHA-512的“阉割版”) | 384 bit | JDK |
SHA-512 | 512 bit | JDK |
-
优点:破解难度高,不可逆
-
缺点:可以通过穷举法进行破解
public class SHAUtils { //加密,不可逆 public static String encrypt(String data) { byte[] dataBytes = data.getBytes(); MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("SHA-512"); md5.update(dataBytes); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] resultBytes = md5.digest(); StringBuilder sb = new StringBuilder(); for (byte b : resultBytes) { String hex = Integer.toHexString(0xFF & b); if(hex.length() == 1) { sb.append("0").append(hex); } else { sb.append(hex); } } return sb.toString(); } }
2.MD5
MD5算法,生成的摘要长度为 128 bit。
应用场景:一致性验证 / 生成摘要对摘要加密。
-
优点:不可逆,压缩性,不容易修改,容易计算
-
缺点:穷举法可以破解
public class MD5Utils { //字符串加密 public static String encryptStr(String data) { byte[] dataBytes = data.getBytes(); MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); md5.update(dataBytes); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] resultBytes = md5.digest(); StringBuilder sb = new StringBuilder(); for (byte b : resultBytes) { String hex = Integer.toHexString(0xFF & b); if(hex.length() == 1) { sb.append("0").append(hex); } else { sb.append(hex); } } return sb.toString(); } //文件加密 public static String encryptFile(String filePath) { String result = ""; FileInputStream fis = null; File file = new File(filePath); StringBuilder sb = new StringBuilder(); try { fis = new FileInputStream(file); MappedByteBuffer byteBuffer = fis.getChannel().map(FileChannel.MapMode.READ_ONLY,0,file.length()); MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(byteBuffer); byte[] resultBytes = md5.digest(); for (byte b : resultBytes) { String hex = Integer.toHexString(0xFF & b); if(hex.length() == 1) { sb.append("0").append(hex); } else { sb.append(hex); } } } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } /** * 多次MD5加密 * @param repeatTimes 重复加密次数 */ public static String repeatEncrypt(String data,int repeatTimes) { if(TextUtils.isEmpty(data)) { return ""; } String result = encryptStr(data); for (int i = 0; i < repeatTimes - 1; i++) { result = encryptStr(result); } return encryptStr(result); } /** * MD5加盐 * 方式: * 1. string + key(盐值) 然后MD5加密 * 2. 用 string 明文的 hashcode 作为盐,然后MD5加密 * 3. 随机生成一串字符串作为盐值,然后MD5加密 * * 该方法采用 string + key * @param data * @param salt * @return */ public static String encryptSalt(String data, String salt) { if(TextUtils.isEmpty(data)) { return ""; } StringBuilder sb = new StringBuilder(); try { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] resultBytes = md5.digest((data + salt).getBytes()); for (byte b : resultBytes) { String hex = Integer.toHexString(0xFF & b); if(hex.length() == 1) { sb.append("0").append(hex); } else { sb.append(hex); } } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return sb.toString(); } }
3、MAC算法
HMAC(keyed-Hash Message Authentication Code):含有密钥的散列函数算法
包含了 MD、SHA 两个系列的消息摘要算法,只是在原有的MD和SHA算法的基础上添加了密钥。
融合了MD,SHA:
MD系列:HmacMD2,HmacMD4,HmacMD5
SHA系列:HmacSHA1,HmacSHA224,HmacSHA256,HmacSHA38,HmacSHA512
算法 | 摘要长度 | 实现方 |
---|---|---|
HmacMD2 | 128 bit | Bouncy Castle |
HmacMD4 | 128 bit | Bouncy Castle |
HmacMD5 | 128 bit | JDK |
HmacSHA1 | 160 bit | JDK |
HmacSHA224 | 224 bit | Bouncy Castle |
HmacSHA256 | 256 bit | JDK |
HmacSHA384 | 384 bit | JDK |
HmacSHA512 | 512 bit | JDK |
3.XOR
概述:异或加密
原字符或数字 m 与一个数值 k 进行异或运算得到结果 r ,
则用 r 与 k 做异或运算即可还原到 m
public class XORUtils {
//固定key方式加解密
public static String encrypt(String data, int key) {
byte[] dataBytes = data.getBytes();
int length = dataBytes.length;
for (int i = 0; i < length; i++) {
dataBytes[i] ^= key;
}
return new String(dataBytes);
}
//固定key方式解密
public byte[] decrypt(byte[] bytes, int key) {
int len = bytes.length;
for (int i = len - 1; i > 0; i--) {
bytes[i] = (byte) (bytes[i] ^ bytes[i - 1]);
}
bytes[0] = (byte) (bytes[0] ^ key);
return bytes;
}
//不固定key方式加密
public byte[] encrypt(byte[] bytes) {
int len = bytes.length;
int key = 0x12;
for (int i = 0; i < len; i++) {
bytes[i] = (byte) (bytes[i] ^ key);
key = bytes[i];
}
return bytes;
}
//不固定key方式解密
public byte[] decrypt(byte[] bytes) {
int len = bytes.length;
int key = 0x12;
for (int i = len - 1; i > 0; i--) {
bytes[i] = (byte) (bytes[i] ^ bytes[i - 1]);
}
bytes[0] = (byte) (bytes[0] ^ key);
return bytes;
}
}
-
优点:两个变量的互换(不借助第三个变量),简单的数据加密
-
缺点:加密方式简单
4.Base64
概述:算不上什么加密算法,只是对数据进行编码传输
public class Base64Utils {
//字符串编码
public static String encodedStr(String data) {
return Base64.encodeToString(data.getBytes(), Base64.DEFAULT);
}
//字符串解码
public static String decodedStr(String data) {
return new String(Base64.decode(data, Base64.DEFAULT));
}
//文件编码
public static String encodedFile(String filePath) {
String result = "";
File file = new File(filePath);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
byte[] buffer = new byte[(int) file.length()];
fis.read(buffer);
result = Base64.encodeToString(buffer, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
/**
* 文件解码
* 解码后保存到指定目录,并返回解码后的内容
*/
public static String decodedFile(String filePath, String data) {
String result = "";
File file = new File(filePath);
FileOutputStream fos = null;
try {
byte[] decodeBytes = Base64.decode(data.getBytes(), Base64.DEFAULT);
result = new String(decodeBytes);
fos = new FileOutputStream(file);
fos.write(decodeBytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
从上述简单的介绍,我们发现,算法分为了两大类:
1)对称加密算法
对称加密算法可以互逆,即通过key加密,也可以通过key来解密
2)非对称加密算法
非对称加密则不可互逆