zgq105 / blog

2 stars 0 forks source link

Java中常用加密算法总结 #35

Open zgq105 opened 5 years ago

zgq105 commented 5 years ago

image

1. 什么是加密算法?作用?

加密算法指通过算法的手段保证数据的安全性和完整性。可以防止数据在网络传输过程中或者在存储介质中被恶意篡改和窃取。

2. 加密算法分类

2.1 单向散列加密

2.1.1 定义?特征?

单向加密又称为不可逆加密算法,其密钥是由加密散列函数生成的。单向散列函数一般用于产生消息摘要,密钥加密等。 算法特征:

2.1.2 MD5

MD5是RSA数据安全公司开发的一种单向散列算法,非可逆,相同的明文产生相同的密文。是一种信息摘要算法。

代码实现:

public static String md5(String str) {
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            return new String(digest.digest(str.getBytes()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

2.1.3 SHA

SHA是Secure Hash Algorithm的缩写,叫安全散列算法。SHA家族的五个算法,分别是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512。以SHA-1为例,代码实现如下:

public static String encrypt(String str)  {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();

            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";
            for (int i = 0; i < digest.length; i++) {
                shaHex = Integer.toHexString(digest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            return hexstr.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

2.1.4 CRC-32

确切的说CRC不算是信息摘要算法。它的原理也是散列函数。CRC-32主要用于提供校验功能。代码实现如下:

 public static String encrypt(String str) {
        CRC32 c32 = new CRC32();
        c32.update(str.getBytes());
        return Long.toHexString(c32.getValue());
    }

注意:该算法输入不一致,输出长度不定。

2.1.5 应用场景

单向散列加密一般用于产生消息摘要,密钥加密等。

2.2 对称加密

2.2.1 定义?特征?

对称加密也加单秘钥加密,即加密和解密使用的都是同一个秘钥。 算法特征:

加密工具:

2.2.2 DES

DES是Data Encryption Standard的缩写,即数据加密标准;速度较快,适用于加密大量数据的场合。代码实现如下:

public class DesUtil {

    private static final String algorithm="DES";
    /**
     * 生成秘钥
     *
     * @return
     */
    public static byte[] greateKey() {
        KeyGenerator keyGen = null;//密钥生成器
        try {
            keyGen = KeyGenerator.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        keyGen.init(new SecureRandom());
        SecretKey secretKey = keyGen.generateKey();//生成密钥
        byte[] key = secretKey.getEncoded();//密钥字节数组
        return key;
    }

    /**
     * 加密
     *
     * @param key  秘钥
     * @param data 需要加密的数据
     * @return
     */
    public static String encrypt(byte[] key, String data) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, algorithm);//恢复密钥
            Cipher cipher = Cipher.getInstance("DES");//Cipher完成加密或解密工作类
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);//对Cipher初始化,加密模式

            byte[] decode = Base64.decode(data);

            byte[] cipherByte = cipher.doFinal(decode);//加密data
            return Base64.encodeBytes(cipherByte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密
     *
     * @param key
     * @param data
     * @return
     */
    public static String decrypt(byte[] key, String data) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, algorithm);//恢复密钥
            Cipher cipher = Cipher.getInstance("DES");//Cipher完成加密或解密工作类
            cipher.init(Cipher.DECRYPT_MODE, secretKey);//对Cipher初始化,解密模式

            byte[] decode = Base64.decode(data);

            byte[] cipherByte = cipher.doFinal(decode);//解密data
            return Base64.encodeBytes(cipherByte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

注意事项:

2.2.3 3DES

是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。实现方式和DES一致,不在叙述。

2.2.4 AES

AES是Advanced Encryption Standard的缩写,即高级加密标准;是下一代的加密算法标准,速度快,安全级别高,支持128、192、256、512位密钥的加密。代码实现如下:

 /**
     * 生成秘钥
     *
     * @return
     */
    public static byte[] greateKey() {
        KeyGenerator keyGen = null;
        try {
            keyGen = KeyGenerator.getInstance("AES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        keyGen.init(128,new SecureRandom());
        SecretKey secretKey = keyGen.generateKey();
        byte[] key = secretKey.getEncoded();
        return key;
    }

    /**
     * 加密
     *
     * @param key  秘钥
     * @param data 需要加密的数据
     * @return
     */
    public static String encrypt(byte[] key, String data) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            byte[] decode = Base64.decode(data);

            byte[] cipherByte = cipher.doFinal(decode);
            return Base64.encodeBytes(cipherByte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密
     *
     * @param key
     * @param data
     * @return
     */
    public static String decrypt(byte[] key, String data) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);

            byte[] decode = Base64.decode(data);

            byte[] cipherByte = cipher.doFinal(decode);
            return Base64.encodeBytes(cipherByte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

2.2.5 Blowfish

Blowfish是一个64位分组及可变密钥长度的分组密码算法,可用来加密64Bit长度的字符串。代码实现如下:

 /**
     * @return
     * @throws Exception
     */
    public static Key keyGenerator() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish");
        keyGenerator.init(128);
        return keyGenerator.generateKey();
    }

    /**
     * 加密
     *
     * @param key
     * @param data
     * @return
     * @throws Exception
     */
    public static String encrypt(Key key, String data) throws Exception {
        Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] decode = Base64.decode(data);
        byte[] bytes = cipher.doFinal(decode);
        return Base64.encodeBytes(bytes);
    }

    /**
     * 解密
     *
     * @param key
     * @param data
     * @return
     * @throws Exception
     */
    public static String decrypt(Key key, String data) throws Exception {
        Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decode = Base64.decode(data);
        byte[] bytes = cipher.doFinal(decode);
        return Base64.encodeBytes(bytes);
    }

2.2.6 应用场景

对称加密加解密效率高,系统开销小,适合进行大数据量的加解密。

2.3 非对称加密

2.3.1 定义?特征?

非对称加密也称为公钥加密,由一对公钥和私钥组成。公钥是从私钥提取出来的。可以用公钥加密,再用私钥解密,这种情形一般用于公钥加密;也可以用私钥加密,用公钥解密,常用于数字签名,因此非对称加密的主要功能就是加密和数字签名。 算法特征:

公钥加密(注意这里John使用Mary的公钥进行加密) image

私钥加密(注意这里John使用自己的私钥进行加密) image

注:非对称加密算法很少用来加密数据,速度太慢,通常用来实现身份验证;事实上,非对称加密的主要作用也就是身份验证;

如何确认通信方证书的合法性?

主要是通过第三方CA(Certificate Authority)。CA为每个使用公开密钥的用户签发一个含CA签名的证书。CA本身也有一个证书和私钥。假设以CA向用户A签发证书流程为例:

  1. CA首先生成一对公钥和私钥,并自签署一个CA证书certificate。
  2. 用户A向CA提供自己的基本信息和自己的公钥。
  3. CA先对用户A的基本信息和公钥计算一个特征码,然后CA再使用自己的私钥对特征码进行加密,加密生成的字符串(数字签名)、A的公钥、A的基本信息共同组成了CA签发的数字证书。

通过CA实现了身份验证,那如何保证数据的机密性呢?

实际数据通信过程中,身份确认完毕之后,通常使用对称加密方式来加密数据。那么对称加密的秘钥如何确定呢?

  1. 秘钥交换(Internet Key Exchange, IKE)算法。
  2. 公钥加密的方式协商秘钥。

2.3.2 RSA

由 RSA公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的;既可以实现加密,又可以实现签名。

2.3.3 DSA

DSA是Digital Signature Algorithm的缩写,即数字签名算法,是一种标准的 DSS(数字签名标准)

2.3.4 应用场景

主要适用于身份认证场景。

3. 小结

通常单向散列加密一般用于消息摘要;对称加密主要适用于大数据量的加密(加密速度快);而非对称加密适用于做身份认证,由于加密数据慢,不太合适用于数据加密。通常,非对称加密和对称加密、散列函数、秘钥交换等结合使用,共同完成整个网络加密的过程。