Android开发中对于数据的传输和保存一定会使用加密技术,加密算法是最普遍的安保手段,多数情况数据加密后在需要使用源数据时需要再进行解密,但凡是都有例外。下面从可逆加密、不可逆、不纯粹加密三种方式记录一下常见的加解密算法。

加密技术包括两个元素:算法和密钥:算法使用密钥将明文数据变成无法辨识的密文。

以下代码是点击事件里调用SecurityUtil工具类,加解密算法都再SecurityUtil中实现。

1、可逆加密:分为对称加密和非对加密

1.1对称加密

加密和解密使用的同一套密钥,包括:DES、3DES、AES等

以AES为例:

被加密的明文

public static final String CONTENT = "suibianxie888888888";

密钥

public static final String SECRET_KEY = "6a8w0c91kc7";
public static final String SECRET_KEY_PREFIX = "aw098";



aesTv.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        try {
            String encryptAES = SecurityUtil.encryptAES( CONTENT, SECRET_KEY+SECRET_KEY_PREFIX);
            Log.e(TAG, "onClick: encryptAES= "+encryptAES );

            String value = SecurityUtil.decryptAES(encryptAES, SECRET_KEY+SECRET_KEY_PREFIX);
            Log.e(TAG, "onClick: decryptAES = "+value);
        }catch (Exception e){
            Log.e(TAG, "onClick: decryptAES -Exception= "+e.getMessage() );
        }
    }
});

    /**
     * AES加密
     * @throws Exception  此处实际有好多个Exception,偷懒直接抛Exception了
     */
    public static String encryptAES(String data, String secretKey) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(secretKey.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
            byte[] bEncData = cipher.doFinal(data.getBytes());
//            return com.android.api.utils.Base64.encode(bEncData);
            return Base64.encodeToString(bEncData, Base64.NO_WRAP);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }



/**
 * AES 解密
 * @param cipherText
 * @param secretKey
 * @return
 * @throws Exception
 */
public static String decryptAES(String cipherText, String secretKey){
    try {
        byte[] encrypted1 = Base64.decode(cipherText, Base64.NO_WRAP);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(secretKey.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] original = cipher.doFinal(encrypted1);
        String originalString = new String(original);
        return originalString;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

AES加密和解密日志打印:

1.2  非对称加密

加密和解密分别使用不同的密钥,包括:SM2、SM4、RSA

2、不可逆加密

无解,理论上谁都别想解开,包括:MD5、SHA系列,MD5和SHA系列,SHA-1之外的SHA系列称作SHA2算法,SHA系列比MD5安全性更高而SHA2的都高于SHA-1。SHA-x 后面的x代表加密后的字符串长度,SHA-1加密后固定160位。常用于用户密码和文件完整性校验。

2.1 MD5加密

拥有以下特质:

压缩性:无论多大加密后都生成128位(16字节)的数据,通常用它的16进制字面值输出是一个32位长度的字符串;  

容易计算性质:通过原数据很容易计算出MD5值;   

抗修改性:随便修改一个字节重新计算的MD5值千差万别;   

抗碰撞性:知道数据和MD5值,很小概率找到相同MD5值的原数据。

public static final String CONTENT = "suibianxie888888888";


md5Tv.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.e(TAG, "onClick: md5Tv-string= "+ SecurityUtil.encryptMD5(CONTENT) );

Log.e(TAG, "onClick: md5Tv-bytes1= "+SecurityUtil.encryptMD5Bytes(CONTENT.getBytes()) );


    }
});
// 16进制下数字到字符的映射数组
public static String[] hexDigits = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
        "a", "b", "c", "d", "e", "f" };



// 对字符串进行MD5编码
public static String encryptMD5(String originstr) {
    if (originstr != null) {
        return encryptMD5Bytes(originstr.getBytes());
    }else {
        return null;
    }
}



public static String encryptMD5Bytes(byte[] originstr) {
    if (originstr != null) {
        try {
            // 创建具有指定算法名称的信息摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 使用指定的字节数组对摘要进行最后的更新,然后完成摘要计算
            byte[] results = md.digest(originstr);
            // 将得到的字节数组编程字符串返回
            String resultString = byteArrayToHexString(results);
            return resultString.toUpperCase();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    return null;
}



// 转换字节数组为十六进制字符串
public static String byteArrayToHexString(byte[] b) {
    StringBuffer resultsb = new StringBuffer();
    int i = 0;
    for (i = 0; i < b.length; i++) {
        resultsb.append(byteToHexString(b[i]));
    }
    return resultsb.toString();
}
//以下代码是对字符串进行MD5加密的相关代码

// 将字节转化成十六进制的字符串
private static String byteToHexString(byte b) {
    int n = b;
    if (n < 0) {
        n = 256 + n;
    }
    int d1 = n / 16;
    int d2 = n / 16;
    return hexDigits[d1] + hexDigits[d2];
}

MD5日志:

SHA1和SHA256:

public static final String CONTENT = "suibianxie888888888";

sha1Tv.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

//SHA1算法
        String fileSHA1 = SecurityUtil.getFileSHA1(CONTENT);
        Log.e(TAG, "onClick:  sha1Tv="+fileSHA1 );

//SHA256算法
        String sha_256 = SecurityUtil.SHA_256(CONTENT);
        Log.e(TAG, "onClick:  sha_256="+sha_256 );
    }
});

// 获取文件的SHA1值
public static String getFileSHA1(String text) {
    if (text.isEmpty()){
        return "";
    }
    try{
        text = text.trim();
        byte[] bytes = text.getBytes("UTF-8");
        return getFileSHA1(bytes);
    }catch (Exception e){
        return "";
    }
}

// 获取文件的SHA1值
public static String getFileSHA1(byte[] bytes) {
    StringBuffer strResult = new StringBuffer();
    MessageDigest md;
    try {
        md = MessageDigest.getInstance("SHA-1");
        md.update(bytes);
        byte[] encryptedBytes = md.digest();
        String stmp;
        for (int n = 0; n < encryptedBytes.length; n++) {
            stmp = (Integer.toHexString(encryptedBytes[n] & 0XFF));
            if (stmp.length() == 1) {
                strResult.append("0");
                strResult.append(stmp);
            } else {
                strResult.append(stmp);
            }
        }
        return strResult.toString();
    } catch (Exception e) {
        return "";
    }
}



/**
 * SHA加密
 * @param strText 明文
 * @return
 */
public static String SHA_256(final String strText){
    // 返回值
    String strResult = null;
    // 是否是有效字符串
    if (strText != null && strText.length() > 0){
        try{
            // SHA 加密开始
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            // 传入要加密的字符串
            messageDigest.update(strText.getBytes());
            byte byteBuffer[] = messageDigest.digest();
            StringBuffer strHexString = new StringBuffer();
            for (int i = 0; i < byteBuffer.length; i++){
                String hex = Integer.toHexString(0xff & byteBuffer[i]);
                if (hex.length() == 1){
                    strHexString.append('0');
                }
                strHexString.append(hex);
            }
            strResult = strHexString.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    return strResult;
}

SHA1和SHA256算法日志打印:

3、不纯粹加密

Base64,经它运算后表面看是变形了,但不属于真的加密,开发中也经常遇到。一种不算严格意义上的加解密,把字符串转换成以"=="双等号结尾的串。

未完结,持续更新中。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部