Android常用加密方式

2022-08-29 18:24:56 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

加密解密简介

加密技术是最常用的安全保密手段,利用技术手段把重要的数据变为乱码(加密)传送,到达目的地后再用相同或不同的手段还原(解密)。加密技术包括两个元素:算法和密钥。算法是将普通的信息或者可以理解的信息与一串数字(密钥)结合,产生不可理解的密文的步骤,密钥是用来对数据进行编码和解密的一种算法。在安全保密中,可通过适当的钥加密技术和管理机制来保证网络的信息通信安全。

加迷解密分类

分为不可逆和可逆,可逆又分为对称密钥体制和非对称密钥体制两种。

秘钥加密技术的密码体制分为对称密钥体制和非对称密钥体制两种。数据加密技术分为两类,即对称加密(私人密钥加密)和非对称加密(公开秘钥加密)。对称加密以数据加密标准(DES,Data Encryption Standard)算法为典型代表,非对称加密通常以RSA(Rivest Shamir Ad1eman)算法为代表。对称加密的加密秘钥和解密密钥相同,而非对称加密的加密密钥和解密密钥不同,加密密钥可以公开而解密密钥需要保密。

不可逆

单项的加密,不能解密。

MD5、SHA、HMAC这三种加密算法,可谓是非可逆加密,就是不可解密的加密方法。

我们通常只把他们作为加密的基础,单纯的以上三种的加密并不可靠。 MD5、SHA 可以通过暴力碰撞算法破解。

对称加密

对称加密指的就是加密和解密使用同一个秘钥,所以叫做对称加密。对称加密只有一个秘钥,作为私钥。

对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的秘钥,即加密密钥也可以用作解密密钥,这种方法在密码学中叫做对称加密算法,对称加密算法使用起来简单快捷,密钥较短,且破译困难,除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高。IDEA加密标准由PGP(Pretty Good Privacy)系统使用。

对称性加密算法有:AES、DES、3DES

非对称加密

非对称加密指的是:加密和解密使用不同的秘钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。

非对称加密指的是:加密和解密使用不同的秘钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。

1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。相对于“对称加密算法”这种方法也叫做“非对称加密算法”。与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密 (privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

非对称性算法有:RSA、DSA、ECC

散列/哈希算法有:MD5、SHA1

其他常用算法:Base64

BASE64

Base64严格地说,属于编码格式,而非加密算法,用于二进制内容转换为可编辑的文本内容。

Base64也会经常用作一个简单的“加密”来保护某些数据,而真正的加密通常都比较繁琐。

编码后的内容,是由64个字符(大小写英文字母 0-9 / (= 补位符,填充字符))组成的序列,成为Base64。可逆的编码方式。

常见于邮件、http加密,截取http信息,你就会发现登录操作的用户名、密码字段通过BASE64加密的。

Android中自带的Base64加密算法:

代码语言:javascript复制
  String s = "xiaoyehai";

        //加密
        String encode = Base64.encodeToString(s.getBytes(), Base64.NO_WRAP);

        //解密
        byte[] decode = Base64.decode(encode.getBytes(), Base64.DEFAULT);
        Log.e("xyh", "encode: "   encode); //eGlhb3llaGFp
        Log.e("xyh", "decode: "  new String(decode,0,decode.length)); //xiaoyehai

在encode的时候,会有一个参数Flags(即上面代码中的Base64.DEFAULT)这个参数有什么用呢?根据Android SDK的描述,这种参数有5个:

DEFAULT 这个参数是默认,使用默认的方法来加密 CRLF 这个参数看起来比较眼熟,它就是Win风格的换行符,意思就是使用CRLF 这一对作为一行的结尾而不是Unix风格的LF NO_PADDING 这个参数是略去加密字符串最后的”=” NO_WRAP 这个参数意思是略去所有的换行符(设置后CRLF就没用了) URL_SAFE 这个参数意思是加密时不使用对URL和文件名有特殊意义的字符来作为加密字符,具体就是以-和 _ 取代 和/

MD5

MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。

MD5本质是一种散列函数,用以提供消息的完整性保护。

单项的加密,不能解密,长度固定(32位)。

通过对任意长度的信息逐位进行计算,产生一个二进制长度为128位(十六进制长度就是32位)的 hash 值, 不同的文件产生相同的hash的可能性是非常小。

特点:

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

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

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

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

5.不可逆:MD5理论上是不可逆的(但是现在已经可以暴力破解了)。

但实际上MD5不是一种加密算法,只是一种算法,因为它是一个不可逆的过程,即 MD5 生成消息摘要后是不能通过结果解析得到原来的内容。

使用场景:

1.验证密码:只要算法不变,就能和服务器上的MD5匹配;在用户注册时,会将密码进行md5加密,存到数据库中。这样可以防止那些可以看到数据库数据的人,恶意操作了。

2.文件完整性的校验:当下载一个文件时,服务器返回的信息包括这个文件的md5,在本地下载完毕时进行md5加密,将两个md5值进行比较,如果一致则说明文件完整没有丢包现象。

MessageDigest 通过其getInstance系列静态函数来进行实例化和初始化。MessageDigest 对象通过使用 update 方法处理数据。任何时候都可以调用 reset 方法重置摘要。一旦所有需要更新的数据都已经被更新了,应该调用 digest 方法之一完成哈希计算并返回结果。

对于给定数量的更新数据,digest 方法只能被调用一次。digest 方法被调用后,MessageDigest 对象被重新设置成其初始状态。

MD5加密工具类

代码语言:javascript复制
/** * Created by : Administrator * Create date : 2019/5/16 22:34 * description : md5加密工具类 */
public class MD5Utils { 
   

      public static String md5(String s) { 
   
        if (s == null) { 
   
            return "";
        }
        try { 
   
            //初始化MessageDigest对象
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");

            //(可选)调用reset方法重置要传入进行加密的数据
            messageDigest.reset();

            //调用update方法传入要进行加密的byte数据
            messageDigest.update(s.getBytes("UTF-8"));

            //调用digest方法对传入的数据进行加密
            byte[] byteArray = messageDigest.digest();
            // java中一个byte为8个二进制位,16*8=128
            //Log.e("xyh", "md5: "   byteArray.length); //16
            StringBuffer md5StrBuff = new StringBuffer();
            for (int i = 0; i < byteArray.length;   i) { 
   
                //转换为16进制,0xFF也可以写成255
                String hexString = Integer.toHexString(0xFF & byteArray[i]);
                Log.e("xyh", "md5: "  hexString);
                if (hexString.length() == 1) { 
   
                    md5StrBuff.append("0").append(hexString);
                } else { 
   
                    md5StrBuff.append(hexString);
                }
            }

            return md5StrBuff.toString();

        } catch (Exception e) { 
   
            e.printStackTrace();
        }
        return "";
    }

    public static String md5(byte[] target, int len) { 
   
        try { 
   
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            messageDigest.update(target, 0, len);
            byte[] byteArray = messageDigest.digest();
            StringBuffer md5StrBuff = new StringBuffer();
            for (int i = 0; i < byteArray.length;   i) { 
   
                if (Integer.toHexString(255 & byteArray[i]).length() == 1) { 
   
                    md5StrBuff.append("0").append(Integer.toHexString(255 & byteArray[i]));
                } else { 
   
                    md5StrBuff.append(Integer.toHexString(255 & byteArray[i]));
                }
            }

            return md5StrBuff.toString();
        } catch (Exception e) { 
   
            e.printStackTrace();
        }
        return "";
    }

    /** * 获取文件的MD5 * * @param file * @return */
    public static String getFileMD5(File file) { 
   
        if (!file.isFile()) { 
   
            return null;
        } else { 
   
            MessageDigest digest = null;
            FileInputStream in = null;
            byte[] buffer = new byte[1024];

            try { 
   
                digest = MessageDigest.getInstance("MD5");
                in = new FileInputStream(file);

                while (true) { 
   
                    int len;
                    if ((len = in.read(buffer, 0, 1024)) == -1) { 
   
                        in.close();
                        break;
                    }

                    digest.update(buffer, 0, len);
                }
            } catch (Exception var6) { 
   
                var6.printStackTrace();
                return null;
            }

            BigInteger bigInt = new BigInteger(1, digest.digest());
            return bigInt.toString(16);
        }
    }

    /** * 获取文件夹的MD5 * * @param file * @param listChild * @return */
    public static Map<String, String> getDirMD5(File file, boolean listChild) { 
   
        if (!file.isDirectory()) { 
   
            return null;
        } else { 
   
            Map<String, String> map = new HashMap();
            File[] files = file.listFiles();

            for (int i = 0; i < files.length;   i) { 
   
                File f = files[i];
                if (f.isDirectory() && listChild) { 
   
                    map.putAll(getDirMD5(f, listChild));
                } else { 
   
                    String md5 = getFileMD5(f);
                    if (md5 != null) { 
   
                        map.put(f.getPath(), md5);
                    }
                }
            }
            return map;
        }
    }
}

SHA

安全散列算法,数字签名工具 , 长度比MD5要长,所以更安全,但是加密的效率要比MD5慢一些.

安全散列算法SHA (Secure Hash Algorithm),用于确保信息传输完整一致。SHA基于MD5实现。

是美国国家标准技术研究所发布的国家标准FIPS PUB 180,最新的标准已经于2008年更新到FIPS PUB 180-3。其中规定了SHA-1,SHA-224,SHA-256,SHA-384,和SHA-512这几种单向散列算法。SHA-1,SHA-224和SHA-256适用于长度不超过264二进制位的消息。SHA-384和SHA-512适用于长度不超过2128二进制位的消息。

SHA1有如下特性:

不可以从消息摘要中复原信息; 两个不同的消息不会产生同样的消息摘要。

著名的图片加载框架Glide在缓存key时就采用的此加密 文件的秒传功能,以及相同的v4包冲突都是可以根据sha1值进行比对的

代码语言:javascript复制
/** * 使用sha-1方式进行加密 * @return */
       public static String digest(String content){ 
   
        StringBuilder builder = new StringBuilder();
        try { 
   
            MessageDigest msgDitest = MessageDigest.getInstance("SHA-1");
            msgDitest.update(content.getBytes());
            byte[] digests = msgDitest.digest();
            //将每个字节转为16进制
            for (int i=0;i<digests.length;i  ){ 
   
                builder.append(Integer.toHexString(digests[i] & 0xff  8));// 8为加盐操作
            }
        } catch (NoSuchAlgorithmException e) { 
   
            e.printStackTrace();
        }
        return  builder.toString();
       }

AES加密

AES加密是一种高级加密标准,是一种区块加密标准。它是一个对称密码,就是说加密和解密用相同的密钥。WPA/WPA2经常用的加密方式就是AES加密算法。

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。 这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用,Android 中的AES 加密 秘钥 key 必须为16/24/32位字节,否则抛异常。

代码语言:javascript复制
package com.xiaoyehai.sdwydc.utils;

import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import com.xiaoyehai.sdwydc.constant.AppConstant;

import java.security.Provider;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/** * AES加密解密 * Created by xiaoyehai on 2018/12/28 0028. */

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

    /** * 生成随机数,可以当做动态的密钥 加密和解密的密钥必须一致,不然将不能解密 */
    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;
    }

    /** * 对密钥进行处理 * * @param seed * @return * @throws Exception */
    private static byte[] getRawKey(byte[] seed) throws Exception { 
   
        KeyGenerator kgen = KeyGenerator.getInstance(AES);
        //for android
        SecureRandom sr = null;
        // 在4.2以上版本中,SecureRandom获取方式发生了改变
        int sdk_version = android.os.Build.VERSION.SDK_INT;
        if (sdk_version > 23) { 
     // Android 6.0 以上
            sr = SecureRandom.getInstance(SHA1PRNG, new CryptoProvider());
        } else if (android.os.Build.VERSION.SDK_INT >= 17) { 
      //4.2及以上
            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;
    }

    /** * 加密 */
    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);
            return new String(Base64.encode(result, Base64.DEFAULT));
        } 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(CBC_PKCS5_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    /** * 解密 */
    public static String decrypt(String key, String encrypted) { 
   
        if (TextUtils.isEmpty(encrypted)) { 
   
            return encrypted;
        }
        try { 
   
            // byte[] enc = Base64Decoder.decodeToBytes(encrypted);
            byte[] enc = Base64.decode(encrypted, Base64.DEFAULT);
            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(CBC_PKCS5_PADDING);
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    //二进制转字符
    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));
    }


    // 增加 CryptoProvider 类

    public static class CryptoProvider extends Provider { 
   
        /** * Creates a Provider and puts parameters */
        public CryptoProvider() { 
   
            super("Crypto", 1.0, "HARMONY (SHA1 digest; SecureRandom; SHA1withDSA signature)");
            put("SecureRandom.SHA1PRNG",
                    "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl");
            put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
        }
    }
}

DES加密

DES(Data Encryption Standard,数据加密算法) 是IBM公司于1975年研究成功并公开发表的,是一种堆成加密算法.

代码语言:javascript复制
 	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以上版本的调用方法

/* * 生成随机数,可以当做动态的密钥 加密和解密的密钥必须一致,不然将不能解密 */
    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));
    }
  // 对密钥进行处理
    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);
    }
/** * 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(TRANSFORMATION);
            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;
        }
    }
  /** * 获取编码后的值 * * @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(TRANSFORMATION);
            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。

RSA加密

RSA加密算法是一种非对称加密算法,非对称加密算法需要两个密钥:公共密钥和私有密钥。公钥和私钥是配对的,用公钥加密的数据只有配对的私钥才能解密。

RSA对加密数据的长度有限制,一般为密钥的长度值-11,要加密较长的数据,可以采用数据截取的方法,分段加密。

特点是加密速度比较慢,但是安全性比较高;

使用场景:

文件或数据在本地使用公钥或私钥加密,加密后的数据传送到服务器,服务器使用同一套密钥中的私钥或者公钥进行解密。

代码语言:javascript复制
public class RSAUtils { 
   
    //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding"
    private static String sTransform = "RSA/NONE/PKCS1Padding";

    //进行Base64转码时的flag设置,默认为Base64.DEFAULT
    private static int sBase64Mode = Base64.DEFAULT;
    //初始化方法,设置参数
    public static void init(String transform,int base64Mode){ 
   
        sTransform = transform;
        sBase64Mode = base64Mode;
    }
    //产生密钥对
    public static KeyPair generateRSAKeyPair(int keyLength){ 
   
        KeyPair keyPair=null;
        try { 
   
            KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA");
            //设置密钥长度
            keyPairGenerator.initialize(keyLength);
            //产生密钥对
            keyPair=keyPairGenerator.generateKeyPair();
        } catch (NoSuchAlgorithmException e) { 
   
            e.printStackTrace();
        }
        return keyPair;
    }

    /** * 加密或解密数据的通用的方法,srcData:待处理的数据;key:公钥或者私钥,mode指 * 加密还是解密,值为Cipher.ENCRYPT_MODE或者Cipher.DECRYPT_MODE */
    public static byte[]processDAta(byte[]srcData, Key key,int mode){ 
   
        //用来保存处理的结果
        byte[]resultBytes=null;
        //构建Cipher对象,需要传入一个字符串,格式必须为"algorithm/mode/padding"或者"algorithm/",意为"算法/加密模式/填充方式"
        try { 
   
            Cipher cipher=Cipher.getInstance("RSA/NONE/PKCS1Padding");
            //初始化Cipher,mode指定是加密还是解密,key为公钥或密钥
            cipher.init(mode,key);
            //处理数据
            resultBytes=cipher.doFinal(srcData);
        } catch (Exception e) { 
   
            e.printStackTrace();
        }
        return resultBytes;
    }
    //使用公钥加密数据,结果用Base64转码
    public static String encryptDataByPublicKey(byte[]srcData, PublicKey publicKey){ 
   
        byte[]resultBytes=processDAta(srcData,publicKey,Cipher.ENCRYPT_MODE);
        return Base64.encodeToString(resultBytes,sBase64Mode);
    }
    //使用私钥解密,结果用Base64转码
    public static byte[]decryptDataByPrivate(String encryptedData, PrivateKey privateKey){ 
   
        byte[]bytes=Base64.decode(encryptedData,sBase64Mode);
        return processDAta(bytes,privateKey,Cipher.DECRYPT_MODE);
    }

    //使用私钥解密,返回解码数据
    public static String decryptToStrByPrivate(String encryptedData,PrivateKey privateKey){ 
   
        return new String(decryptDataByPrivate(encryptedData,privateKey));
    }

}

总结

(1) 对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。

(2) 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。

(3) 解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。

使用

在Android开发中,一般只用到Base64,MD5,RSA,DES。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/145359.html原文链接:https://javaforall.cn

0 人点赞