1.MD5算法简介

项目中无论是密码的存储或者说判断文件是否是同一文件,都会用到MD5算法,它是由MD2、MD3、MD4演变过来的,是一种单向加密算法,同时也是不可逆的一种的加密方式。

MD5加密算法实现:

1.)计算字符串MD5值

public static String md5(String string) {
 if (TextUtils.isEmpty(string)) {
 return “”;
 }
 MessageDigest md5 = null;
 try {
 md5 = MessageDigest.getInstance(“MD5”);
 byte[] bytes = md5.digest(string.getBytes());
 String result = “”;
 for (byte b : bytes) {
 String temp = Integer.toHexString(b & 0xff);
 if (temp.length() == 1) {
 temp = “0” + temp;
 }
 result += temp;
 }
 return result;
 } catch (NoSuchAlgorithmException e) {
 e.printStackTrace();
 }
 return “”;
 }


2.)计算文件的MD5值

// 计算文件的 MD5 值
 public static String md5(File file) {
 if (file == null || !file.isFile() || !file.exists()) {
 return “”;
 }
 FileInputStream in = null;
 String result = “”;
 byte buffer[] = new byte[8192];
 int len;
 try {
 MessageDigest md5 = MessageDigest.getInstance(“MD5”);
 in = new FileInputStream(file);
 while ((len = in.read(buffer)) != -1) {
 md5.update(buffer, 0, len);
 }
 byte[] bytes = md5.digest();
for (byte b : bytes) {
            String temp = Integer.toHexString(b & 0xff);
            if (temp.length() == 1) {
                temp = "0" + temp;
            }
            result += temp;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        if(null!=in){
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return result;
}

增加md5的安全性
3.)对字符串多次MD5加密
4.)MD5加盐

加盐的方式也是多种多样

string+key(盐值key)然后进行MD5加密

用string明文的hashcode作为盐,然后进行MD5加密
随机生成一串字符串作为盐,然后进行MD5加密

public static String md5(String string, String slat) {
 if (TextUtils.isEmpty(string)) {
 return “”;
 }
 MessageDigest md5 = null;
 try {
 md5 = MessageDigest.getInstance(“MD5”);
 byte[] bytes = md5.digest((string + slat).getBytes());
 String result = “”;
 for (byte b : bytes) {
 String temp = Integer.toHexString(b & 0xff);
 if (temp.length() == 1) {
 temp = “0” + temp;
 }
 result += temp;
 }
 return result;
 } catch (NoSuchAlgorithmException e) {
 e.printStackTrace();
 }
 return “”;
 }

2.Base64编码算法简介

什么Base64编码?

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,Base64并不是安全领域的加密算法,其实Base64只能算是一个编码算法,对数据内容进行编码来适合传输。标准Base64编码解码无需额外信息即完全可逆,即使你自己自定义字符集设计一种类Base64的编码方式用于数据加密,在多数场景下也较容易破解。Base64编码本质上是一种将二进制数据转成文本数据的方案。对于非二进制数据,是先将其转换成二进制形式,然后每连续6比特(2的6次方=64)计算其十进制值,根据该值在A--Z,a--z,0--9,+,/ 这64个字符中找到对应的字符,最终得到一个文本字符串。基本规则如下几点:

标准Base64只有64个字符(英文大小写、数字和+、/)以及用作后缀等号;
Base64是把3个字节变成4个可打印字符,所以Base64编码后的字符串一定能被4整除(不算用作后缀的等号);
等号一定用作后缀,且数目一定是0个、1个或2个。这是因为如果原文长度不能被3整除,Base64要在后面添加\0凑齐3n位。为了正确还原,添加了几个\0就加上几个等号。显然添加等号的数目只能是0、1或2;
严格来说Base64不能算是一种加密,只能说是编码转换。

1.)字符串进行Base64编码

String encodedString = Base64.encodeToString(“whoislcj”.getBytes(), Base64.DEFAULT);
 Log.e(“Base64”, “Base64---->” + encodedString);


2.)字符串进行Base64解码

String decodedString =new String(Base64.decode(encodedString,Base64.DEFAULT));
 Log.e(“Base64”, “Base64---->” + decodedString);


3.)对文件进行Base64编码

File file = new File("/storage/emulated/0/pimsecure_debug.txt");
 FileInputStream inputFile = null;
 try {
 inputFile = new FileInputStream(file);
 byte[] buffer = new byte[(int) file.length()];
 inputFile.read(buffer);
 inputFile.close();
 encodedString = Base64.encodeToString(buffer, Base64.DEFAULT);
 Log.e(“Base64”, “Base64---->” + encodedString);
 } catch (Exception e) {
 e.printStackTrace();
 }


4.)对文件进行Base64解码

File desFile = new File("/storage/emulated/0/pimsecure_debug_1.txt");
 FileOutputStream fos = null;
 try {
 byte[] decodeBytes = Base64.decode(encodedString.getBytes(), Base64.DEFAULT);
 fos = new FileOutputStream(desFile);
 fos.write(decodeBytes);
 fos.close();
 } catch (Exception e) {
 e.printStackTrace();
 }

3.DES算法简介

DES加密介绍:

DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究,

后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,24小时内即可被破解。
DES加密使用方式:

1.)DesUtil常量类介绍

private final static String HEX = "0123456789ABCDEF";
private final static String TRANSFORMATION = "DES/CBC/PKCS5Padding";//DES是加密方式 CBC是工作模式 PKCS5Padding是填充模式
private final static String IVPARAMETERSPEC = "01020304";初始化向量参数,AES 为16bytes. DES 为8bytes.
private final static String ALGORITHM = "DES";//DES是加密方式
private static final String SHA1PRNG = "SHA1PRNG"; SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法

2.)动态生成秘钥

长度不能够小于8位字节 因为DES固定格式为128bits,即8bytes。

/*
  • 生成随机数,可以当做动态的密钥 加密和解密的密钥必须一致,不然将不能解密
•  */
 public static String generateKey() {
 try {
 SecureRandom localSecureRandom = SecureRandom.getInstance(SHA1PRNG);
 byte[] bytes_key = new byte[20];
 localSecureRandom.nextBytes(bytes_key);
 String str_key = toHex(bytes_key);
 return str_key;
 } catch (Exception e) {
 e.printStackTrace();
 }
 return null;
 }
//二进制转字符
 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));
 }

3.)处理秘钥Key的两种方式

第一种:

// 对密钥进行处理
private static Key getRawKey(String key) throws Exception {
    KeyGenerator kgen = KeyGenerator.getInstance(ALGORITHM);
    //for android
    SecureRandom sr = null;
    // 在4.2以上版本中,SecureRandom获取方式发生了改变
    if (android.os.Build.VERSION.SDK_INT >= 17) {
        sr = SecureRandom.getInstance(SHA1PRNG, "Crypto");
    } else {
        sr = SecureRandom.getInstance(SHA1PRNG);
    }
    // for Java
    // secureRandom = SecureRandom.getInstance(SHA1PRNG);
    sr.setSeed(key.getBytes());
    kgen.init(64, sr); //DES固定格式为64bits,即8bytes。
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();
    return new SecretKeySpec(raw, ALGORITHM);
}

第二种:

// 对密钥进行处理
 private static Key getRawKey(String key) throws Exception {
 DESKeySpec dks = new DESKeySpec(key.getBytes());
 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
 return keyFactory.generateSecret(dks);
 }


4.)加密实现

/**
 * DES算法,加密
 *
 * @param data 待加密字符串
 * @param key 加密私钥,长度不能够小于8位
 * @return 加密后的字节数组,一般结合Base64编码使用
 */
 public static String encode(String key, String data) {
 return encode(key, data.getBytes());
 }/**
 * DES算法,加密
 *
 * @param data 待加密字符串
 * @param key  加密私钥,长度不能够小于8位
 * @return 加密后的字节数组,一般结合Base64编码使用
 */
public static String encode(String key, byte[] data) {
    try {
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec(IVPARAMETERSPEC.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, getRawKey(key), iv);
        byte[] bytes = cipher.doFinal(data);
        return Base64.encodeToString(bytes, Base64.DEFAULT);
    } catch (Exception e) {
        return null;
    }
}
/**
 * DES算法,加密
 *
 * @param data 待加密字符串
 * @param key  加密私钥,长度不能够小于8位
 * @return 加密后的字节数组,一般结合Base64编码使用
 */
public static String encode(String key, byte[] data) {
    try {
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec(IVPARAMETERSPEC.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, getRawKey(key), iv);
        byte[] bytes = cipher.doFinal(data);
        return Base64.encodeToString(bytes, Base64.DEFAULT);
    } catch (Exception e) {
        return null;
    }
}

5.)解密实现

/**
 * 获取编码后的值
 *
 * @param key
 * @param data
 * @return
 */
public static String decode(String key, String data) {
    return decode(key, Base64.decode(data, Base64.DEFAULT));
}

/**
 * DES算法,解密
 *
 * @param data 待解密字符串
 * @param key  解密私钥,长度不能够小于8位
 * @return 解密后的字节数组
 */
public static String decode(String key, byte[] data) {
    try {
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec(IVPARAMETERSPEC.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, getRawKey(key), iv);
        byte[] original = cipher.doFinal(data);
        String originalString = new String(original);
        return originalString;
    } catch (Exception e) {
        return null;
    }
}

DES知识扩展:3DES

3DES是DES加密算法的一种模式,它使用3条64位的密钥对数据进行三次加密。数据加密标准(DES)是美国的一种由来已久的加密标准,它使用对称密钥加密法。3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法。

DES与AES比较:

当时被问起采用DES加密内心深处我是拒绝的。单纯从名字上看AES(Advanced Encryption Standard)高级加密标准,安全性要高于DES,其实AES的出现本身就是为了取代DES的,AES具有比DES更好的安全性、效率、灵活性,所以对称加密优先采用AES。

4.AES算法简介

什么是aes加密?

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。

接下来我们来实际看下具体怎么实现:

对于AesUtils类常量简介:

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以上版本的调用方法

如何生成一个随机Key?

/*
 * 生成随机数,可以当做动态的密钥 加密和解密的密钥必须一致,不然将不能解密
 */
 public static String generateKey() {
 try {
 SecureRandom localSecureRandom = SecureRandom.getInstance(SHA1PRNG);
 byte[] bytes_key = new byte[20];
 localSecureRandom.nextBytes(bytes_key);
 String str_key = toHex(bytes_key);
 return str_key;
 } catch (Exception e) {
 e.printStackTrace();
 }
 return null;
 }

Aes密钥处理

// 对密钥进行处理
 private static byte[] getRawKey(byte[] seed) throws Exception {
 KeyGenerator kgen = KeyGenerator.getInstance(AES);
 //for android
 SecureRandom sr = null;
 // 在4.2以上版本中,SecureRandom获取方式发生了改变
 if (android.os.Build.VERSION.SDK_INT >= 17) {
 sr = SecureRandom.getInstance(SHA1PRNG, “Crypto”);
 } else {
 sr = SecureRandom.getInstance(SHA1PRNG);
 }
 // for Java
 // secureRandom = SecureRandom.getInstance(SHA1PRNG);
 sr.setSeed(seed);
 kgen.init(128, sr); //256 bits or 128 bits,192bits
 //AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥版本则有14个加密循环。
 SecretKey skey = kgen.generateKey();
 byte[] raw = skey.getEncoded();
 return raw;
 }


Aes加密过程

/*
 * 加密
 */
 public static String encrypt(String key, String cleartext) {
 if (TextUtils.isEmpty(cleartext)) {
 return cleartext;
 }
 try {
 byte[] result = encrypt(key, cleartext.getBytes());
 return Base64Encoder.encode(result);
 } catch (Exception e) {
 e.printStackTrace();
 }
 return null;
 }
/*
* 加密
*/
private static byte[] encrypt(String key, byte[] clear) throws Exception {
    byte[] raw = getRawKey(key.getBytes());
    SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    byte[] encrypted = cipher.doFinal(clear);
    return encrypted;
}

Aes解密过程

/*
 * 解密
 */
 public static String decrypt(String key, String encrypted) {
 if (TextUtils.isEmpty(encrypted)) {
 return encrypted;
 }
 try {
 byte[] enc = Base64Decoder.decodeToBytes(encrypted);
 byte[] result = decrypt(key, enc);
 return new String(result);
 } catch (Exception e) {
 e.printStackTrace();
 }
 return null;
 }
/*
 * 解密
 */
private static byte[] decrypt(String key, byte[] encrypted) throws Exception {
    byte[] raw = getRawKey(key.getBytes());
    SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    byte[] decrypted = cipher.doFinal(encrypted);
    return decrypted;
}

5.RSA算法简介

什么是Rsa加密?

RSA算法是最流行的公钥密码算法,使用长度可以变化的密钥。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。

最终得到的N和e就是“公钥”,d就是“私钥”,发送方使用N去加密数据,接收方只有使用d才能解开数据内容。

RSA的安全性依赖于大数分解,小于1024位的N已经被证明是不安全的,而且由于RSA算法进行的都是大数计算,使得RSA最快的情况也比DES慢上很多倍,这是RSA最大的缺陷,因此通常只能用于加密少量数据或者加密密钥,但RSA仍然不失为一种高强度的算法。

几个全局变量解说:

public static final String RSA = "RSA";// 非对称加密密钥算法
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;// 当前秘钥支持加密的最大字节数

使用方式
1.首先生成秘钥对

/**
 * 随机生成RSA密钥对
 *
 * @param keyLength 密钥长度,范围:512~2048
 * 一般1024
 * @return
/
 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 原文
 */
 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 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);
 }

6.异或加密算法简介

什么是异或加密?

异或运算中,如果某个字符(或数值)x 与 一个数值m 进行异或运算得到y,则再用y 与 m 进行异或运算就可以还原为 x ,因此应用这个原理可以实现数据的加密解密功能。

异或运算使用场景?

两个变量的互换(不借助第三个变量),效率要求较高的场景。

数据的简单加密解密

异或加密解密实现?

这种方式加密解密 算法一样

public byte[] encrypt(byte[] bytes) {
    if (bytes == null) {
        return null;
    }
    int len = bytes.length;
    int key = 0x12;
    for (int i = 0; i < len; i++) {
        bytes[i] ^= key;
    }
    return bytes;
}

测试加密解密

byte[] bytes = encrypt(“whoislcj”.getBytes());//加密
 String str1 = new String(encrypt(bytes));//解密