Android数据加密之Rsa/MD5/Aes/Des加密算法归纳总结

加密算法

1.加密算法通常分为对称性加密算法和非对称性加密算法:对于对称性加密算法,信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是对数据进行 加解密了。非对称算法与之不同,发送双方A,B事先均生成一堆密匙,然后A将自己的公有密匙发送给B,B将自己的公有密匙发送给A,如果A要给B发送消息,则先需要用B的公有密匙进行消息加密,然后发送给B端,此时B端再用自己的私有密匙进行消息解密,B向A发送消息时为同样的道理。

Android数据加密之Rsa加密:非对称加密

Android数据加密之MD5加密:非对称加密

Android数据加密之Aes加密:对称加密

Android数据加密之Des加密:对称加密

Android数据加密之Base64编码算法

Android数据加密之MD5加密

前言:

      项目中无论是密码的存储或者说判断文件是否是同一文件,都会用到MD5算法,今天来总结一下MD5加密算法。

1、什么是MD5加密?

     MD5英文全称“Message-Digest Algorithm 5”,翻译过来是“消息摘要算法5”,由MD2、MD3、MD4演变过来的,是一种单向加密算法,是不可逆的一种的加密方式。 MD5 是非对称的加密算法

2、MD5加密有哪些特点?

  1. 压缩性:任意长度的数据,算出的MD5值长度都是固定的。

  2. 容易计算:从原数据计算出MD5值很容易。

  3. 抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。

  4. 强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。

3、MD5应用场景:

  1. 一致性验证

  2. 数字签名

  3. 安全访问认证

4、MD5加密安全性探讨:

      虽然说MD5加密本身是不可逆的,但并不是不可破译的,网上有关MD5解密的网站数不胜数,破解机制采用穷举法,就是我们平时说的跑字典。所以如何才能加大MD5破解的难度呢?

1.)对字符串多次MD5加密

2.)MD5加盐

     加盐的方式也是多种多样

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

  • 用string明文的hashcode作为盐,然后进行MD5加密

  • 随机生成一串字符串作为盐,然后进行MD5加密

 

MD5加密工具类:

package com.wangshuchang.utils;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

 

/**

* Salt MD5 加强模块<br>

* 提供 16 位与 32 位 MD5 加密与其 Salt 加密功能<p>

*

* Salt 加密方法调用:<br>

*         MD5Utilsmd5 = new MD5Utils();<br>

*         String [] _tmp = md5.salt32("明文"); <br>

        System.out.println(_tmp[0] + "\t" + _tmp[1]);

*

* @author WangSC

*/

public class MD5Utils {

    

    /**

     * 随机密钥长度

     */

    private static final int _KEYTLENGTH = 6;

 

    public UtilMD5() {

    }

 

    /**

     * 生成随机密钥

     *

     * @param length

     *            密钥长度

     */

    private String getRandomKeyt(int length) throws Exception {

        if (length < 1)

            throw new Exception("密钥长度不能小于 1");

        StringBuilder sb = new StringBuilder("0123456789abcdefghijklmnopqrstuvwxyz");

        int len = sb.length();

        System.out.println("len " + len);

        String _keyt = "";

        for (int i = 0; i < length; i++) {

            int ran = (int) (Math.random() * len);

            System.out.println("ran " + ran);

            int index = ran % len;

            System.out.println("index " + index);

            System.out.println("char " + sb.charAt(index));

            _keyt += sb.charAt(index);

            

        }

        return _keyt;

    }

 

    /**

     * 32位标准 MD5 加密

     *

     * @param plainText

     *            明文

     * @return 密文<br>

     *         返回 Null 值则出现异常

*/

    public String cell32(String plainText) {

        try {

            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update(plainText.getBytes());

            byte b[] = md.digest();

            int i;

            StringBuffer buf = new StringBuffer("");

            for (int offset = 0; offset < b.length; offset++) {

                i = b[offset];

                if (i < 0)

                    i += 256;

                if (i < 16)

                    buf.append("0");

                buf.append(Integer.toHexString(i));

            }

            return buf.toString();// 32位的加密

 

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        }

        return null;

    }

 

    /**

     * 32 位 salt 加密

     *

     * @param plainText

     *            明文

     * @return 索引 0 是密文,索引 1 是二次密钥

*/

//    public String[] salt32(String plainText) throws Exception {

//        return salt("cell32", plainText);

//    }

//    

    /**

     * 32 位 salt 加密

     *

     * @param plainText

     *            明文

     * @return 索引 0 是密文,索引 1 是二次密钥

*/

    public String salt32(String plainText) throws Exception {

        return salt1("cell32", plainText);

    }

    

 

    /**

     * 16 位标准 MD5 加密

     *

     * @param plainText

     *            明文

     * @return 密文<br>

     *         返回 Null 值则出现异常

*/

    public String cell16(String plainText) {

        String result = cell32(plainText);

        if (result == null)

            return null;

        return result.toString().substring(8, 24);// 16位的加密

    }

 

    /**

     * 16 位 salt 加密

     *

     * @param plainText

     *            明文

     * @return 索引 0 是密文,索引 1 是二次密钥

*/

    public String[] salt16(String plainText) throws Exception {

        return salt("cell16", plainText);

    }

 

    /**

     * 根据调用的方法名称执行不同的方法

     *

     * @param saltFunctionName

     *            加密的方法名称

*/

    private String[] salt(String saltFunctionName, String plainText)

            throws Exception {

        String _keyt = getRandomKeyt(_KEYTLENGTH);

        return new String[] {(String) this.getClass().getMethod(saltFunctionName, Class.forName("java.lang.String")).invoke(this, (cell32(plainText) + _keyt)), _keyt };

    }

    

    private String salt1(String saltFunctionName, String plainText)

            throws Exception {

        String _keyt = getRandomKeyt(_KEYTLENGTH);

        return (String) this.getClass().getMethod(saltFunctionName, Class.forName("java.lang.String")).invoke(this, cell32(plainText)) + _keyt;

    }

}

MD5解密工具类:

package com.wangshuchang.utils;

/**

 * @author WangSC

 * 解密工具类

 */

public class UtilDecode {

     

     private static final int _KEYTLENGTH = 6;

     

     public static String pack(String base64) {

          String nBase64 = null;

          if (base64 != null) {

              nBase64 = base64.substring(1, base64.length() - 1);

          }

          return nBase64;

     }

     

     /**

      * 去掉加密数据后面的Salt数据

      * @param salt

      * @return

      */

     public static String removeSalt(String salt) {

          String data = null;

          if (salt != null) {

              int len = salt.length() - _KEYTLENGTH;

              if (len > 0) {

                   data = salt.substring(0, len);

              }

          }

          return data;

     }

}

Android数据加密之Aes加密

什么是aes加密?

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

对于AesUtils类常量简介:

private final static String HEX = "0123456789ABCDEF";

    //AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式

private static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";

 

AES加密工具类:

package com.wangshuchang.utils;

import java.math.BigInteger;

import javax.crypto.Cipher;

import javax.crypto.KeyGenerator;

import javax.crypto.spec.SecretKeySpec;

import org.apache.http.util.TextUtils;

 

/**

* @author: WangSC

* @date: 2018/11/22

* @description: AES的加密和解密

* aesEncrypt(content, KEY); 加密

* aesDecrypt(encrypt, KEY); 解密

*/

public class AesUtil {

    //密钥 (需要前端和后端保持一致)

    private static final String KEY = "com_WangSC_@36!";

    //算法

    private static final String ALGORITHMSTR = "Aes/ECB/PKCS5Padding";

 

    /**

     * aes解密

     *

     * @param encrypt 内容

     * @return

     * @throws Exception

     */

    public static String aesDecrypt(String encrypt) {

        try {

            return aesDecrypt(encrypt, KEY);

        } catch (Exception e) {

            e.printStackTrace();

            return "";

        }

    }

 

    /**

     * aes加密

     *

     * @param content

     * @return

     * @throws Exception

     */

    public static String aesEncrypt(String content) {

        try {

            return aesEncrypt(content, KEY);

        } catch (Exception e) {

            e.printStackTrace();

            return "";

        }

    }

 

    /**

     * 将byte[]转为各种进制的字符串

     *

     * @param bytes byte[]

     * @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制

     * @return 转换后的字符串

     */

    public static String binary(byte[] bytes, int radix) {

        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数

    }

 

    /**

     * AES加密

     *

     * @param content    待加密的内容

     * @param encryptKey 加密密钥

     * @return 加密后的byte[]

     * @throws Exception

     */

    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {

        KeyGenerator kgen = KeyGenerator.getInstance("Aes");

        kgen.init(128);

        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);

        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "Aes"));

 

        return cipher.doFinal(content.getBytes("utf-8"));

    }

 

 

    /**

     * AES加密为code

     *

     * @param content    待加密的内容

     * @param encryptKey 加密密钥

     * @return 加密后的code

     * @throws Exception

     */

    public static String aesEncrypt(String content, String encryptKey) throws Exception {

        return parseByte2HexStr(aesEncryptToBytes(content, encryptKey));

    }

 

    /**

     * AES解密

     *

     * @param encryptBytes 待解密的byte[]

     * @param decryptKey   解密密钥

     * @return 解密后的String

     * @throws Exception

     */

    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {

        KeyGenerator kgen = KeyGenerator.getInstance("Aes");

        kgen.init(128);

 

        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);

        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "Aes"));

        byte[] decryptBytes = cipher.doFinal(encryptBytes);

        return new String(decryptBytes);

    }

 

 

    /**

     * 将code AES解密

     *

     * @param encryptStr 待解密的code

     * @param decryptKey 解密密钥

     * @return 解密后的string

     * @throws Exception

     */

    public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {

        return TextUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(parseHexStr2Byte(encryptStr), decryptKey);

    }

 

    /**

     * 将二进制转换成16进制

     *

     * @param buf

     * @return

     */

    public static String parseByte2HexStr(byte buf[]) {

        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < buf.length; i++) {

            String hex = Integer.toHexString(buf[i] & 0xFF);

            if (hex.length() == 1) {

                hex = '0' + hex;

            }

            sb.append(hex.toUpperCase());

        }

        return sb.toString();

    }

 

    /**

     * 将16进制转换为二进制

     *

     * @param hexStr

     * @return

     */

    public static byte[] parseHexStr2Byte(String hexStr) {

        if (hexStr.length() < 1)

            return null;

        byte[] result = new byte[hexStr.length() / 2];

        for (int i = 0; i < hexStr.length() / 2; i++) {

            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);

            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);

            result[i] = (byte) (high * 16 + low);

        }

        return result;

    }

}

Android数据加密之Base64编码算法

前言:

      前面学习总结了平时开发中遇见的各种数据加密方式,最终都会对加密后的二进制数据进行Base64编码,起到一种二次加密的效果,其实呢Base64从严格意义上来说的话不是一种加密算法,而是一种编码算法,为何要使用Base64编码呢?它解决了什么问题?这也是本文探讨的东西?

1、什么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不能算是一种加密,只能说是编码转换。

下图为Base64编码表

2、Base64编码的用处?

    在计算机中任何数据都是按ascii码存储的,而ascii码的128~255之间的值是不可见字符。而在网络上交换数据时,比如说从A地传到B地,往往要经过多个路由设备,由于不同的设备对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。所以就先把数据先做一个Base64编码,统统变成可见字符,这样出错的可能性就大降低了。

3、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();

}

 5.)针对Base64.DEFAULT参数说明

无论是编码还是解码都会有一个参数Flags,Android提供了以下几种

DEFAULT 这个参数是默认,使用默认的方法来加密

NO_PADDING 这个参数是略去加密字符串最后的”=”

NO_WRAP 这个参数意思是略去所有的换行符(设置后CRLF就没用了)

CRLF 这个参数看起来比较眼熟,它就是Win风格的换行符,意思就是使用CR LF这一对作为一行的结尾而不是Unix风格的LF

URL_SAFE 这个参数意思是加密时不使用对URL和文件名有特殊意义的字符来作为加密字符,具体就是以-和_取代+和/

 

RSA封装类 ,完整的RSA加密和解密 public class RSAUtilEncrypt { public static final String KEY_ALGORTHM = "RSA";// public static final String KEY_ALGORTHM_RSA_ECB_PKCS1PADDING = "RSA/ECB/PKCS1Padding"; public static String RSA_PUBLIC_KEY = "rsa_public_key"; public static String RSA_PRIVATE_KEY = "rsa_private_key"; private int KeySize = 1024; private Map keyMap; private static String RSA = "RSA"; private static PublicKey publickey; public RSAUtilEncrypt(int KeySize,String publickey) { this.KeySize = KeySize; try { this.publickey=generatePublicKeyByString(publickey); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private RSAPublicKey generatePublicKeyByString(String publicKeyStr) throws Exception { try { BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("No Algorthm,Checked by cemung!"); } catch (InvalidKeySpecException e) { throw new Exception("InvalidKeySpec!"); } catch (IOException e) { throw new Exception("Io exception!"); } catch (NullPointerException e) { throw new Exception("Illegle pointer reference!"); } } // Encypt public byte[] RSAEncrypt(byte[] data, RSAPublicKey publickey) throws Exception { Cipher cipher = Cipher.getInstance(KEY_ALGORTHM_RSA_ECB_PKCS1PADDING); cipher.init(Cipher.ENCRYPT_MODE, this.publickey); byte[] cipherbytes = cipher.doFinal(data); return cipherbytes; } // Encypt public byte[] RSAEncrypt(byte[] data) throws Exception { Cipher cipher = Cipher.getInstance(KEY_ALGORTHM_RSA_ECB_PKCS1PADDING); cipher.init(Cipher.ENCRYPT_MODE, this.publickey); byte[] cipherbytes = cipher.doFinal(data); return cipherbytes; } // Get Public key with format byte[] public byte[] getPublicKeyByte() { RSAPublicKey pubkey = (RSAPublicKey) keyMap.get(RSA_PUBLIC_KEY); return pubkey.getEncoded(); } public static byte[] decryptBASE64(String key) throws Exception { return (new BASE64Decoder()).decodeBuffer(key); } public static String encryptBASE64(byte[] key) throws Exception { return (new BASE64Encoder()).encodeBuffer(key); } public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception { byte[] keyBytes = decryptBASE64(key); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec( keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception { byte[] keyBytes = decryptBASE64(key); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception { byte[] keyBytes = decryptBASE64(key); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data); } 使用方法 private RSAUtilEncrypt rsa = new RSAUtilEncrypt(1024, publikey); /* * 给信息加密,获取密文 */ public String getCiphertext(String str_encrode) { try { byte[] estr = rsa.RSAEncrypt(str_encrode.getBytes()); // 密文 String ciphertext = Base64.encodeToString(estr, Base64.DEFAULT); return ciphertext; } catch (Exception e) { e.printStackTrace(); } return null; } 有疑问的留言
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值